Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Stein Fletcher committed Mar 21, 2020
0 parents commit e0e5be6
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 0 deletions.
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.PHONY: test test-examples docs fmt vet

test:
bash -c 'diff -u <(echo -n) <(gofmt -s -d ./)'
bash -c 'diff -u <(echo -n) <(go vet ./...)'
go test ./...
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# apitest-css-selector

Assertions for [apitest](https:/steinfletcher/apitest) using css selectors.
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module github.com/steinfletcher/apitest-css-selector

go 1.13

require (
github.com/PuerkitoBio/goquery v1.5.1
github.com/steinfletcher/apitest v1.4.4
)
23 changes: 23 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
github.com/PuerkitoBio/goquery v1.5.1 h1:PSPBGne8NIUWw+/7vFBV+kG2J/5MOjbzc7154OaKCSE=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/steinfletcher/apitest v1.4.4 h1:ZT/Wa3J615x7mBuarTf92o43AseYfHEFsLhnl1dBkl4=
github.com/steinfletcher/apitest v1.4.4/go.mod h1:yaYc9GDlj4fa0qUUDywqAmrELlNbDrBwd36Zgo5hMZo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
65 changes: 65 additions & 0 deletions selector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package selector

import (
"fmt"
"net/http"

"github.com/PuerkitoBio/goquery"
"github.com/steinfletcher/apitest"
)

type selectionMatcher func(i int, selection *goquery.Selection) bool

func FirstTextValue(selection string, expectedTextValue string) apitest.Assert {
return newSelectionAssert(selection, expectedTextValue, func(i int, selection *goquery.Selection) bool {
if i == 0 {
if selection.Text() == expectedTextValue {
return true
}
}
return false
})
}

func NthTextValue(n int, selection string, expectedTextValue string) apitest.Assert {
return newSelectionAssert(selection, expectedTextValue, func(i int, selection *goquery.Selection) bool {
if i == n {
if selection.Text() == expectedTextValue {
return true
}
}
return false
})
}

func ContainsTextValue(selection string, expectedTextValue string) apitest.Assert {
return newSelectionAssert(selection, expectedTextValue, func(i int, selection *goquery.Selection) bool {
if selection.Text() == expectedTextValue {
return true
}
return false
})
}

func newSelectionAssert(selection string, expectedTextValue string, matcher selectionMatcher) apitest.Assert {
return func(response *http.Response, request *http.Request) error {
doc, err := goquery.NewDocumentFromReader(response.Body)
if err != nil {
return err
}

var found bool
doc.Find(selection).Each(func(i int, selection *goquery.Selection) {
if matcher(i, selection) {
found = true
}
})

if !found {
return fmt.Errorf("result did not contain expected value '%s' for selector '%s'",
expectedTextValue, selection)
}

return nil
}
}
124 changes: 124 additions & 0 deletions selector_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package selector_test

import (
"net/http"
"testing"

"github.com/steinfletcher/apitest"

selector "github.com/steinfletcher/apitest-css-selector"
)

func TestSelector_FirstTextValue(t *testing.T) {
tests := map[string]struct {
selector string
responseBody string
expected string
}{
"first text value": {
selector: "h1",
responseBody: `<html>
<head>
<title>My document</title>
</head>
<body>
<h1>Header</h1>
</body>
</html>`,
expected: "Header",
},
"first text value with class": {
selector: ".myClass",
responseBody: `<div class="myClass">content</div>`,
expected: "content",
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
apitest.New().
Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(test.responseBody))
w.WriteHeader(http.StatusOK)
})).
Get("/").
Expect(t).
Status(http.StatusOK).
Assert(selector.FirstTextValue(test.selector, test.expected)).
End()

})
}
}

func TestSelector_NthTextValue(t *testing.T) {
tests := map[string]struct {
selector string
responseBody string
expected string
n int
}{
"second text value": {
selector: ".myClass",
responseBody: `<div>
<div class="myClass">first</div>
<div class="myClass">second</div>
</div>`, expected: "first",
n: 0,
},
"last text value": {
selector: ".myClass",
responseBody: `<div>
<div class="myClass">first</div>
<div class="myClass">second</div>
</div>`, expected: "second",
n: 1,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
apitest.New().
Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(test.responseBody))
w.WriteHeader(http.StatusOK)
})).
Get("/").
Expect(t).
Status(http.StatusOK).
Assert(selector.NthTextValue(test.n, test.selector, test.expected)).
End()

})
}
}

func TestSelector_TextValueContains(t *testing.T) {
tests := map[string]struct {
selector string
responseBody string
expected string
}{
"text value contains": {
selector: ".myClass",
responseBody: `<div>
<div class="myClass">first</div>
<div class="myClass">second</div>
</div>`,
expected: "second",
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
apitest.New().
Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(test.responseBody))
w.WriteHeader(http.StatusOK)
})).
Get("/").
Expect(t).
Status(http.StatusOK).
Assert(selector.ContainsTextValue(test.selector, test.expected)).
End()

})
}
}

0 comments on commit e0e5be6

Please sign in to comment.