Skip to content

Commit 98f7f6c

Browse files
authored
Merge pull request #102 from SimonBaeumer/add-json-assertion
Add json and xml assertion
2 parents 1a31c3e + f8f1d9e commit 98f7f6c

128 files changed

Lines changed: 186388 additions & 20 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# v1.3.0
2+
3+
- Added `xml` assertion to `stdout` and `stderr`
4+
- Added `json` assertin to `stdout` and `stderr`
5+
16
# v1.2.2
27

38
- Rename windows binary `commander-windows-386` to `commander-windows-386.exe`

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ tests:
9797
line-count: 1 # Assert amount of lines
9898
lines: # Assert specific lines
9999
1: "/bin/sh: 1: invalid: not found"
100+
json:
101+
object.attr: hello # Make assertions on json objects
102+
xml:
103+
"//book//auhtor": Steven King # Make assertions on xml documents
100104
exit-code: 127
101105

102106
it has configs:

cmd/commander/commander.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ func createTestCommand() cli.Command {
6565
},
6666
},
6767
Action: func(c *cli.Context) error {
68+
if c.Bool("verbose") {
69+
log.SetOutput(os.Stdout)
70+
}
71+
6872
return app.TestCommand(c.Args().First(), c.Args().Get(1), app.NewAddContextFromCli(c))
6973
},
7074
}

commander_unix.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ tests:
99

1010
it should execute tests:
1111
command: ./commander test ./integration/unix/commander_test.yaml
12-
stdout: ✓ it should exit with error code
12+
stdout:
13+
contains:
14+
- ✓ it should exit with error code
15+
line-count: 15
1316
exit-code: 0
1417

1518
it should assert that commander will fail:

go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
module github.com/SimonBaeumer/commander
22

33
require (
4+
github.com/antchfx/xmlquery v1.1.0
5+
github.com/antchfx/xpath v1.1.0 // indirect
46
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e
57
github.com/pmezard/go-difflib v1.0.0
68
github.com/stretchr/testify v1.3.0
9+
github.com/tidwall/gjson v1.3.2
710
github.com/urfave/cli v1.20.0
11+
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 // indirect
812
gopkg.in/yaml.v2 v2.2.2
913
)

go.sum

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
github.com/antchfx/jsonquery v1.0.0 h1:1Yhk496SrCoY6fJkFZqpXEqbwOw5sFtLns9la4NoK3I=
2+
github.com/antchfx/jsonquery v1.0.0/go.mod h1:h7950pvPrUZzJIflNqsELgDQovTpPNa0rAHf8NwjegY=
3+
github.com/antchfx/xmlquery v1.1.0 h1:vj0kZ1y3Q6my4AV+a9xbWrMYzubw+84zuiKgvfV8vb8=
4+
github.com/antchfx/xmlquery v1.1.0/go.mod h1:/+CnyD/DzHRnv2eRxrVbieRU/FIF6N0C+7oTtyUtCKk=
5+
github.com/antchfx/xpath v1.1.0 h1:mJTvYpiHvxNQRD4Lbfin/FodHVCHh2a5KrOFr4ZxMOI=
6+
github.com/antchfx/xpath v1.1.0/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
17
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
28
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
39
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k=
@@ -7,8 +13,20 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
713
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
814
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
915
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
16+
github.com/tidwall/gjson v1.3.2 h1:+7p3qQFaH3fOMXAJSrdZwGKcOO/lYdGS0HqGhPqDdTI=
17+
github.com/tidwall/gjson v1.3.2/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
18+
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
19+
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
20+
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
21+
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
1022
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
1123
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
24+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
25+
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 h1:p9xBe/w/OzkeYVKm234g55gMdD1nSIooTir5kV11kfA=
26+
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
27+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
28+
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
29+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
1230
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1331
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
1432
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"books": [
3+
{
4+
"author": "J. R. R. Tolkien",
5+
"title": "Lord of the Rings"
6+
},
7+
{
8+
"author": "Joanne K. Rowling",
9+
"title": "Harry Potter"
10+
}
11+
]
12+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<books>
2+
<book>
3+
<author>J. R. R. Tolkien</author>
4+
<title>Lord of the Rngs</title>
5+
</book>
6+
<book>
7+
<author>Joanne K. Rowling</author>
8+
<title>Harry Potter</title>
9+
</book>
10+
</books>

integration/unix/commander_test.yaml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,18 @@ tests:
4343
command: echo lorem ipsum
4444
stdout:
4545
not-contains:
46-
- not contains
46+
- not contains
47+
48+
it should assert json:
49+
command: cat ./integration/unix/_fixtures/book.json
50+
stdout:
51+
json:
52+
books.0.author: J. R. R. Tolkien
53+
books.1.author: Joanne K. Rowling
54+
55+
it should assert xml:
56+
command: cat ./integration/unix/_fixtures/book.xml
57+
stdout:
58+
xml:
59+
/books/0/author: J. R. R. Tokien
60+
/books/1/author: Joanne K. Rowling

pkg/matcher/matcher.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package matcher
22

33
import (
44
"fmt"
5+
"github.com/antchfx/xmlquery"
56
"github.com/pmezard/go-difflib/difflib"
7+
"github.com/tidwall/gjson"
8+
"log"
69
"strings"
710
)
811

@@ -15,6 +18,8 @@ const (
1518
Equal = "equal"
1619
// Not contains matcher type
1720
NotContains = "notcontains"
21+
JSON = "json"
22+
XML = "xml"
1823
)
1924

2025
// NewMatcher creates a new matcher by type
@@ -28,6 +33,10 @@ func NewMatcher(matcher string) Matcher {
2833
return EqualMatcher{}
2934
case NotContains:
3035
return NotContainsMatcher{}
36+
case JSON:
37+
return JSONMatcher{}
38+
case XML:
39+
return XMLMatcher{}
3140
default:
3241
panic(fmt.Sprintf("Validator '%s' does not exist!", matcher))
3342
}
@@ -51,6 +60,7 @@ type TextMatcher struct {
5160
// Match matches both texts
5261
func (m TextMatcher) Match(got interface{}, expected interface{}) MatcherResult {
5362
result := true
63+
5464
if got != expected {
5565
result = false
5666
}
@@ -150,3 +160,83 @@ to not contain
150160
Diff: diff,
151161
}
152162
}
163+
164+
type JSONMatcher struct {
165+
}
166+
167+
func (m JSONMatcher) Match(got interface{}, expected interface{}) MatcherResult {
168+
result := MatcherResult{
169+
Success: true,
170+
Diff: "",
171+
}
172+
173+
json := expected.(map[string]string)
174+
for q, e := range json {
175+
r := gjson.Get(got.(string), q)
176+
if r.Value() == nil {
177+
result.Success = false
178+
result.Diff = fmt.Sprintf(`Query "%s" did not match a path`, q)
179+
break
180+
}
181+
182+
if fmt.Sprintf("%v", r.Value()) != e {
183+
result.Success = false
184+
result.Diff = fmt.Sprintf(`Expected json path "%s" with result
185+
186+
%s
187+
188+
to be equal to
189+
190+
%s`, q, e, r.Value())
191+
break
192+
}
193+
}
194+
195+
return result
196+
}
197+
198+
type XMLMatcher struct {
199+
}
200+
201+
func (m XMLMatcher) Match(got interface{}, expected interface{}) MatcherResult {
202+
result := MatcherResult{
203+
Success: true,
204+
Diff: "",
205+
}
206+
207+
xml := expected.(map[string]string)
208+
for q, e := range xml {
209+
doc, err := xmlquery.Parse(strings.NewReader(got.(string)))
210+
if err != nil {
211+
log.Fatal(err)
212+
}
213+
214+
node, err := xmlquery.Query(doc, q)
215+
if err != nil {
216+
return MatcherResult{
217+
Success: false,
218+
Diff: fmt.Sprintf("Error occured: %s", err),
219+
}
220+
}
221+
222+
if node == nil {
223+
return MatcherResult{
224+
Success: false,
225+
Diff: fmt.Sprintf(`Query "%s" did not match a path`, q),
226+
}
227+
}
228+
229+
if node.InnerText() != e {
230+
result.Success = false
231+
result.Diff = fmt.Sprintf(`Expected xml path "%s" with result
232+
233+
%s
234+
235+
to be equal to
236+
237+
%s`, q, e, node.InnerText())
238+
}
239+
}
240+
241+
return result
242+
}

0 commit comments

Comments
 (0)