Skip to content

Commit 48fe4d5

Browse files
committed
Add check.JSON and assert.JSON.
1 parent 14394d4 commit 48fe4d5

4 files changed

Lines changed: 211 additions & 0 deletions

File tree

pkg/assert/json.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// SPDX-FileCopyrightText: (c) 2025 Rafal Zajac <rzajac@gmail.com>
2+
// SPDX-License-Identifier: MIT
3+
4+
package assert
5+
6+
import (
7+
"github.com/ctx42/testing/pkg/check"
8+
"github.com/ctx42/testing/pkg/tester"
9+
)
10+
11+
// JSON asserts that two JSON strings are equivalent. Returns true if they are,
12+
// otherwise marks the test as failed, writes error message to test log and
13+
// returns false.
14+
//
15+
// assert.JSON(t, `{"hello": "world"}`, `{"foo": "bar"}`)
16+
func JSON(t tester.T, want, have string, opts ...check.Option) bool {
17+
t.Helper()
18+
if e := check.JSON(want, have, opts...); e != nil {
19+
t.Error(e)
20+
return false
21+
}
22+
return true
23+
}

pkg/assert/json_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// SPDX-FileCopyrightText: (c) 2025 Rafal Zajac <rzajac@gmail.com>
2+
// SPDX-License-Identifier: MIT
3+
4+
package assert
5+
6+
import (
7+
"testing"
8+
9+
"github.com/ctx42/testing/internal/affirm"
10+
"github.com/ctx42/testing/pkg/check"
11+
"github.com/ctx42/testing/pkg/tester"
12+
)
13+
14+
func Test_JSON(t *testing.T) {
15+
t.Run("success", func(t *testing.T) {
16+
// --- Given ---
17+
tspy := tester.New(t).Close()
18+
19+
want := ` {"hello": "world"} `
20+
have := " { \"hello\"\t:\n\n \"world\"\n\n\t} "
21+
22+
// --- When ---
23+
got := JSON(tspy, want, have)
24+
25+
// --- Then ---
26+
affirm.True(t, got)
27+
})
28+
29+
t.Run("error", func(t *testing.T) {
30+
// --- Given ---
31+
tspy := tester.New(t)
32+
tspy.ExpectError()
33+
tspy.IgnoreLogs()
34+
tspy.Close()
35+
36+
want := ` {"hello": "world"} `
37+
have := " { \"hello\"\t:\n\n \"ms\"\n\n\t} "
38+
39+
// --- When ---
40+
got := JSON(tspy, want, have)
41+
42+
// --- Then ---
43+
affirm.False(t, got)
44+
})
45+
46+
t.Run("error", func(t *testing.T) {
47+
// --- Given ---
48+
tspy := tester.New(t)
49+
tspy.ExpectError()
50+
tspy.ExpectLogContain(" trail: type.field\n")
51+
tspy.Close()
52+
53+
want := ` {"hello": "world"} `
54+
have := " { \"hello\"\t:\n\n \"ms\"\n\n\t} "
55+
opt := check.WithTrail("type.field")
56+
57+
// --- When ---
58+
got := JSON(tspy, want, have, opt)
59+
60+
// --- Then ---
61+
affirm.False(t, got)
62+
})
63+
}

pkg/check/json.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// SPDX-FileCopyrightText: (c) 2025 Rafal Zajac <rzajac@gmail.com>
2+
// SPDX-License-Identifier: MIT
3+
4+
package check
5+
6+
import (
7+
"encoding/json"
8+
9+
"github.com/ctx42/testing/pkg/notice"
10+
)
11+
12+
// JSON checks that two JSON strings are equivalent. Returns nil if they are,
13+
// otherwise it returns an error with a message indicating the expected and
14+
// actual values.
15+
//
16+
// Example:
17+
//
18+
// check.JSON(`{"hello": "world"}`, `{"foo": "bar"}`)
19+
func JSON(want, have string, opts ...Option) error {
20+
var wantItf, haveItf any
21+
22+
ops := DefaultOptions(opts...)
23+
if err := json.Unmarshal([]byte(want), &wantItf); err != nil {
24+
return notice.New("did not expect unmarshalling error").
25+
Trail(ops.Trail).
26+
Append("argument", "want").
27+
Append("error", "%s", err)
28+
}
29+
if err := json.Unmarshal([]byte(have), &haveItf); err != nil {
30+
return notice.New("did not expect unmarshalling error").
31+
Trail(ops.Trail).
32+
Append("argument", "have").
33+
Append("error", "%s", err)
34+
}
35+
36+
if err := Equal(wantItf, haveItf, WithOptions(ops)); err != nil {
37+
w, _ := json.Marshal(wantItf) // nolint:errchkjson
38+
h, _ := json.Marshal(haveItf) // nolint:errchkjson
39+
return notice.New("expected JSON strings to be equal").
40+
Trail(ops.Trail).
41+
Want("%v", string(w)).
42+
Have("%v", string(h))
43+
}
44+
return nil
45+
}

pkg/check/json_test.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// SPDX-FileCopyrightText: (c) 2025 Rafal Zajac <rzajac@gmail.com>
2+
// SPDX-License-Identifier: MIT
3+
4+
package check
5+
6+
import (
7+
"testing"
8+
9+
"github.com/ctx42/testing/internal/affirm"
10+
)
11+
12+
func Test_JSON(t *testing.T) {
13+
t.Run("equal", func(t *testing.T) {
14+
// --- Given ---
15+
want := ` {"hello": "world"} `
16+
have := " { \"hello\"\t:\n\n \"world\"\n\n\t} "
17+
18+
// --- When ---
19+
err := JSON(want, have)
20+
21+
// --- Then ---
22+
affirm.Nil(t, err)
23+
})
24+
25+
t.Run("not equal", func(t *testing.T) {
26+
// --- Given ---
27+
want := ` {"hello": "world"} `
28+
have := " { \"hello\"\t:\n\n \"ms\"\n\n\t} "
29+
opt := WithTrail("type.field")
30+
31+
// --- When ---
32+
err := JSON(want, have, opt)
33+
34+
// --- Then ---
35+
affirm.NotNil(t, err)
36+
wMsg := "expected JSON strings to be equal:\n" +
37+
" trail: type.field\n" +
38+
" want: {\"hello\":\"world\"}\n" +
39+
" have: {\"hello\":\"ms\"}"
40+
affirm.Equal(t, wMsg, err.Error())
41+
})
42+
43+
t.Run("invalid want JSON", func(t *testing.T) {
44+
// --- Given ---
45+
want := `{!!!}`
46+
have := `{"hello": "world"}`
47+
opt := WithTrail("type.field")
48+
49+
// --- When ---
50+
err := JSON(want, have, opt)
51+
52+
// --- Then ---
53+
affirm.NotNil(t, err)
54+
wMsg := "did not expect unmarshalling error:\n" +
55+
" trail: type.field\n" +
56+
" argument: want\n" +
57+
" error: invalid character '!' looking for beginning of " +
58+
"object key string"
59+
affirm.Equal(t, wMsg, err.Error())
60+
})
61+
62+
t.Run("invalid have JSON", func(t *testing.T) {
63+
// --- Given ---
64+
want := `{"hello": "world"}`
65+
have := `{!!!}`
66+
opt := WithTrail("type.field")
67+
68+
// --- When ---
69+
err := JSON(want, have, opt)
70+
71+
// --- Then ---
72+
affirm.NotNil(t, err)
73+
wMsg := "did not expect unmarshalling error:\n" +
74+
" trail: type.field\n" +
75+
" argument: have\n" +
76+
" error: invalid character '!' looking for beginning of " +
77+
"object key string"
78+
affirm.Equal(t, wMsg, err.Error())
79+
})
80+
}

0 commit comments

Comments
 (0)