From daeccc96c182a34e17c0900deebf61d4d2b04ce4 Mon Sep 17 00:00:00 2001 From: Igor Lazarev Date: Tue, 10 Oct 2023 22:36:51 +0300 Subject: [PATCH 1/3] feature: new assertions --- assertjson/assertjson_test.go | 38 +++++++++++++++++++++++++++++++++++ assertjson/string.go | 32 +++++++++++++++++++++++++++++ test/testdata/object.json | 3 +++ 3 files changed, 73 insertions(+) diff --git a/assertjson/assertjson_test.go b/assertjson/assertjson_test.go index 7be0271..de97d55 100644 --- a/assertjson/assertjson_test.go +++ b/assertjson/assertjson_test.go @@ -42,6 +42,8 @@ func TestFileHas(t *testing.T) { // fluent string assertions json.Node("stringNode").IsString() + json.Node("emptyString").IsString().IsEmpty() + json.Node("stringNode").IsString().IsNotEmpty() json.Node("stringNode").IsString().EqualTo("stringValue") json.Node("stringNode").IsString().EqualToOneOf("stringValue", "nextValue") json.Node("stringNode").IsString().NotEqualTo("invalid") @@ -788,6 +790,40 @@ func TestHas(t *testing.T) { `failed asserting that JSON node "key" is string`, }, }, + { + name: "JSON node is string is empty", + json: `{"key": ""}`, + assert: func(json *assertjson.AssertJSON) { + json.Node("key").IsString().IsEmpty() + }, + }, + { + name: "JSON node is string is empty fails", + json: `{"key": "value"}`, + assert: func(json *assertjson.AssertJSON) { + json.Node("key").IsString().IsEmpty() + }, + wantMessages: []string{ + `failed asserting that JSON node "key": is empty string, actual is "value"`, + }, + }, + { + name: "JSON node is string is not empty", + json: `{"key": "value"}`, + assert: func(json *assertjson.AssertJSON) { + json.Node("key").IsString().IsNotEmpty() + }, + }, + { + name: "JSON node is string is not empty fails", + json: `{"key": ""}`, + assert: func(json *assertjson.AssertJSON) { + json.Node("key").IsString().IsNotEmpty() + }, + wantMessages: []string{ + `failed asserting that JSON node "key": is not empty string`, + }, + }, { name: "JSON node is string equal to", json: `{"key": "value"}`, @@ -1053,6 +1089,8 @@ func TestHas(t *testing.T) { assert: func(json *assertjson.AssertJSON) { json.Node("key"). IsString(). + IsEmpty(). + IsNotEmpty(). EqualTo(""). NotEqualTo(""). EqualToOneOf(""). diff --git a/assertjson/string.go b/assertjson/string.go index 7e76ff6..d6d28ea 100644 --- a/assertjson/string.go +++ b/assertjson/string.go @@ -93,6 +93,38 @@ type StringAssertion struct { value string } +// IsEmpty asserts that the JSON node has a string value equals to empty string. +func (a *StringAssertion) IsEmpty(msgAndArgs ...interface{}) *StringAssertion { + if a == nil { + return nil + } + a.t.Helper() + if a.value != "" { + a.fail( + fmt.Sprintf(`is empty string, actual is "%s"`, a.value), + msgAndArgs..., + ) + } + + return a +} + +// IsNotEmpty asserts that the JSON node has a string value not equals to empty string. +func (a *StringAssertion) IsNotEmpty(msgAndArgs ...interface{}) *StringAssertion { + if a == nil { + return nil + } + a.t.Helper() + if a.value == "" { + a.fail( + `is not empty string`, + msgAndArgs..., + ) + } + + return a +} + // EqualTo asserts that the JSON node has a string value equals to the given value. func (a *StringAssertion) EqualTo(expectedValue string, msgAndArgs ...interface{}) *StringAssertion { if a == nil { diff --git a/test/testdata/object.json b/test/testdata/object.json index b7c7c5c..70163d8 100644 --- a/test/testdata/object.json +++ b/test/testdata/object.json @@ -4,8 +4,11 @@ "nullNode": null, "falseBooleanNode": false, "trueBooleanNode": true, + "emptyString": "", "stringNode": "stringValue", + "zeroInteger": 0, "integerNode": 123, + "zeroFloat": 0.0, "floatNode": 123.123, "uuid": "23e98a0c-26c8-410f-978f-d1d67228af87", "nilUUID": "00000000-0000-0000-0000-000000000000", From 77d71695d7189e04c83cb03bf003a5b7d601d96c Mon Sep 17 00:00:00 2001 From: Igor Lazarev Date: Thu, 25 Jan 2024 22:29:45 +0300 Subject: [PATCH 2/3] feature: new assertions --- README.md | 14 ++++++ assertjson/assertjson_test.go | 80 +++++++++++++++++++++++++++++++++++ assertjson/jwt.go | 13 ++++++ assertjson/numeric.go | 62 +++++++++++++++++++++++++++ assertjson/string.go | 5 +-- 5 files changed, 170 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a1d2a23..116cd2e 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,8 @@ func TestYourAPI(t *testing.T) { // fluent string assertions json.Node("stringNode").IsString() + json.Node("emptyString").IsString().IsEmpty() + json.Node("stringNode").IsString().IsNotEmpty() json.Node("stringNode").IsString().EqualTo("stringValue") json.Node("stringNode").IsString().EqualToOneOf("stringValue", "nextValue") json.Node("stringNode").IsString().NotEqualTo("invalid") @@ -115,6 +117,8 @@ func TestYourAPI(t *testing.T) { // numeric assertions json.Node("integerNode").IsInteger() + json.Node("zeroInteger").IsInteger().IsZero() + json.Node("integerNode").IsInteger().IsNotZero() json.Node("integerNode").IsInteger().EqualTo(123) json.Node("integerNode").IsInteger().NotEqualTo(321) json.Node("integerNode").IsInteger().GreaterThan(122) @@ -123,6 +127,8 @@ func TestYourAPI(t *testing.T) { json.Node("integerNode").IsInteger().LessThanOrEqual(123) json.Node("floatNode").IsFloat() json.Node("floatNode").IsNumber() + json.Node("zeroFloat").IsNumber().IsZero() + json.Node("floatNode").IsNumber().IsNotZero() json.Node("floatNode").IsNumber().EqualTo(123.123) json.Node("floatNode").IsNumber().NotEqualTo(321.123) json.Node("floatNode").IsNumber().EqualToWithDelta(123.123, 0.1) @@ -244,6 +250,14 @@ func TestYourAPI(t *testing.T) { assert.Equal(t, "23e98a0c-26c8-410f-978f-d1d67228af87", json.Node("uuid").IsUUID().Value().String()) assert.Equal(t, "23e98a0c-26c8-410f-978f-d1d67228af87", json.Node("uuid").UUID().String()) + // standalone JWT assertion + assertjson.IsJWT(t, + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaHR0cHM6Ly9hdWRpZW5jZTEuZXhhbXBsZS5jb20iLCJodHRwczovL2F1ZGllbmNlMi5leGFtcGxlLmNvbSJdLCJleHAiOjQ4MjAzNjAxMzEsImlhdCI6MTY2Njc1NjUzMSwiaXNzIjoiaHR0cHM6Ly9pc3N1ZXIuZXhhbXBsZS5jb20iLCJqdGkiOiJhYmMxMjM0NSIsIm5hbWUiOiJKb2huIERvZSIsIm5iZiI6MTY2Njc1NjUzMSwic3ViIjoiaHR0cHM6Ly9zdWJqZWN0LmV4YW1wbGUuY29tIn0.fGUvIn-BV8bPKkZdrxUneew3_qBe-knptL9a_TkNA4M", + func(token *jwt.Token) (interface{}, error) { return []byte("your-256-bit-secret"), nil }, + ).WithPayload(func(json *assertjson.AssertJSON) { + json.Node("name").IsString().EqualTo("John Doe") + }) + // debug helpers json.Node("bookstore", "books", 1).Print() }) diff --git a/assertjson/assertjson_test.go b/assertjson/assertjson_test.go index de97d55..c49e7f2 100644 --- a/assertjson/assertjson_test.go +++ b/assertjson/assertjson_test.go @@ -69,6 +69,8 @@ func TestFileHas(t *testing.T) { // numeric assertions json.Node("integerNode").IsInteger() + json.Node("zeroInteger").IsInteger().IsZero() + json.Node("integerNode").IsInteger().IsNotZero() json.Node("integerNode").IsInteger().EqualTo(123) json.Node("integerNode").IsInteger().NotEqualTo(321) json.Node("integerNode").IsInteger().GreaterThan(122) @@ -83,6 +85,8 @@ func TestFileHas(t *testing.T) { json.Node("integerNode").IsNumberLessThanOrEqual(123) json.Node("floatNode").IsFloat() json.Node("floatNode").IsNumber() + json.Node("zeroFloat").IsNumber().IsZero() + json.Node("floatNode").IsNumber().IsNotZero() json.Node("floatNode").IsNumber().EqualTo(123.123) json.Node("floatNode").IsNumber().NotEqualTo(321.123) json.Node("floatNode").IsNumber().EqualToWithDelta(123.123, 0.1) @@ -229,6 +233,14 @@ func TestFileHas(t *testing.T) { Raw, ) + // standalone JWT assertion + assertjson.IsJWT(t, + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaHR0cHM6Ly9hdWRpZW5jZTEuZXhhbXBsZS5jb20iLCJodHRwczovL2F1ZGllbmNlMi5leGFtcGxlLmNvbSJdLCJleHAiOjQ4MjAzNjAxMzEsImlhdCI6MTY2Njc1NjUzMSwiaXNzIjoiaHR0cHM6Ly9pc3N1ZXIuZXhhbXBsZS5jb20iLCJqdGkiOiJhYmMxMjM0NSIsIm5hbWUiOiJKb2huIERvZSIsIm5iZiI6MTY2Njc1NjUzMSwic3ViIjoiaHR0cHM6Ly9zdWJqZWN0LmV4YW1wbGUuY29tIn0.fGUvIn-BV8bPKkZdrxUneew3_qBe-knptL9a_TkNA4M", + func(token *jwt.Token) (interface{}, error) { return []byte("your-256-bit-secret"), nil }, + ).WithPayload(func(json *assertjson.AssertJSON) { + json.Node("name").IsString().EqualTo("John Doe") + }) + // debug helpers json.Node("bookstore", "books", 1).Print() }) @@ -490,6 +502,40 @@ func TestHas(t *testing.T) { `value at path "key" is not a number`, }, }, + { + name: "JSON node is number is zero", + json: `{"key": 0}`, + assert: func(json *assertjson.AssertJSON) { + json.Node("key").IsNumber().IsZero() + }, + }, + { + name: "JSON node is number is zero fails", + json: `{"key": 1.2}`, + assert: func(json *assertjson.AssertJSON) { + json.Node("key").IsNumber().IsZero() + }, + wantMessages: []string{ + `failed asserting that JSON node "key": is zero, actual is 1.200000`, + }, + }, + { + name: "JSON node is number is not zero", + json: `{"key": 1.2}`, + assert: func(json *assertjson.AssertJSON) { + json.Node("key").IsNumber().IsNotZero() + }, + }, + { + name: "JSON node is number is not zero fails", + json: `{"key": 0}`, + assert: func(json *assertjson.AssertJSON) { + json.Node("key").IsNumber().IsNotZero() + }, + wantMessages: []string{ + `failed asserting that JSON node "key": is not zero`, + }, + }, { name: "JSON node is number equal to", json: `{"key": 123.123}`, @@ -654,6 +700,40 @@ func TestHas(t *testing.T) { `value at path "key" is float, not integer`, }, }, + { + name: "JSON node is integer is zero", + json: `{"key": 0}`, + assert: func(json *assertjson.AssertJSON) { + json.Node("key").IsInteger().IsZero() + }, + }, + { + name: "JSON node is integer is zero fails", + json: `{"key": 1}`, + assert: func(json *assertjson.AssertJSON) { + json.Node("key").IsInteger().IsZero() + }, + wantMessages: []string{ + `failed asserting that JSON node "key": is zero, actual is 1`, + }, + }, + { + name: "JSON node is integer is not zero", + json: `{"key": 1}`, + assert: func(json *assertjson.AssertJSON) { + json.Node("key").IsInteger().IsNotZero() + }, + }, + { + name: "JSON node is integer is not zero fails", + json: `{"key": 0}`, + assert: func(json *assertjson.AssertJSON) { + json.Node("key").IsInteger().IsNotZero() + }, + wantMessages: []string{ + `failed asserting that JSON node "key": is not zero`, + }, + }, { name: "JSON node is integer equal to", json: `{"key": 123}`, diff --git a/assertjson/jwt.go b/assertjson/jwt.go index 1163ae1..896a548 100644 --- a/assertjson/jwt.go +++ b/assertjson/jwt.go @@ -11,6 +11,19 @@ import ( "github.com/stretchr/testify/assert" ) +// IsJWT asserts that the string contains valid JWT. +func IsJWT(t TestingT, value string, keyFunc jwt.Keyfunc) *JWTAssertion { + t.Helper() + token, err := jwt.Parse(value, keyFunc) + if err == nil { + return &JWTAssertion{t: t, token: token} + } + + assert.Fail(t, fmt.Sprintf(`failed asserting that string contains JWT: %s`, err.Error())) + + return nil +} + // JWTAssertion is used to build a chain of assertions for the JWT node. type JWTAssertion struct { t TestingT diff --git a/assertjson/numeric.go b/assertjson/numeric.go index 0ef34b7..6b452c5 100644 --- a/assertjson/numeric.go +++ b/assertjson/numeric.go @@ -126,6 +126,37 @@ type NumberAssertion struct { value float64 } +// IsZero asserts that the JSON node has a numeric value equals to zero. +func (a *NumberAssertion) IsZero(msgAndArgs ...interface{}) *NumberAssertion { + if a == nil { + return nil + } + a.t.Helper() + + if a.value != 0 { + a.fail( + fmt.Sprintf(`is zero, actual is %f`, a.value), + msgAndArgs..., + ) + } + + return nil +} + +// IsNotZero asserts that the JSON node has a numeric value not equals to zero. +func (a *NumberAssertion) IsNotZero(msgAndArgs ...interface{}) *NumberAssertion { + if a == nil { + return nil + } + a.t.Helper() + + if a.value == 0 { + a.fail(`is not zero`, msgAndArgs...) + } + + return nil +} + // EqualTo asserts that the JSON node has a numeric value equals to the given value. func (a *NumberAssertion) EqualTo(expected float64, msgAndArgs ...interface{}) *NumberAssertion { if a == nil { @@ -259,6 +290,37 @@ type IntegerAssertion struct { value int } +// IsZero asserts that the JSON node has an integer value equals to 0. +func (a *IntegerAssertion) IsZero(msgAndArgs ...interface{}) *IntegerAssertion { + if a == nil { + return nil + } + a.t.Helper() + + if a.value != 0 { + a.fail( + fmt.Sprintf(`is zero, actual is %d`, a.value), + msgAndArgs..., + ) + } + + return nil +} + +// IsNotZero asserts that the JSON node has an integer value not equals to 0. +func (a *IntegerAssertion) IsNotZero(msgAndArgs ...interface{}) *IntegerAssertion { + if a == nil { + return nil + } + a.t.Helper() + + if a.value == 0 { + a.fail(`is not zero`, msgAndArgs...) + } + + return nil +} + // EqualTo asserts that the JSON node has an integer value equals to the given value. func (a *IntegerAssertion) EqualTo(expected int, msgAndArgs ...interface{}) *IntegerAssertion { if a == nil { diff --git a/assertjson/string.go b/assertjson/string.go index d6d28ea..b61b148 100644 --- a/assertjson/string.go +++ b/assertjson/string.go @@ -116,10 +116,7 @@ func (a *StringAssertion) IsNotEmpty(msgAndArgs ...interface{}) *StringAssertion } a.t.Helper() if a.value == "" { - a.fail( - `is not empty string`, - msgAndArgs..., - ) + a.fail(`is not empty string`, msgAndArgs...) } return a From a2f2e2cf9321e9ec125a9dbc41be61490ddbc79b Mon Sep 17 00:00:00 2001 From: Igor Lazarev Date: Thu, 25 Jan 2024 22:34:45 +0300 Subject: [PATCH 3/3] feature: new assertions --- .github/workflows/main.yml | 2 +- .golangci.yml | 18 ++++++++++++++++++ assertjson/assertjson_test.go | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 99fcbe6..252f086 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,7 +25,7 @@ jobs: - name: Run golangci-lint uses: golangci/golangci-lint-action@v2 with: - version: v1.51 + version: v1.54 - name: Run tests run: go test -v $(go list ./... | grep -v vendor) diff --git a/.golangci.yml b/.golangci.yml index ac39134..17e422f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -72,3 +72,21 @@ issues: - scopelint - gochecknoglobals - goerr113 + +linters-settings: + depguard: + rules: + main: + files: + - $all + - "!$test" + - "!**/test/**/*" + allow: + - $gostd + - github.com + test: + files: + - "$test" + allow: + - $gostd + - github.com diff --git a/assertjson/assertjson_test.go b/assertjson/assertjson_test.go index c49e7f2..af0ecd5 100644 --- a/assertjson/assertjson_test.go +++ b/assertjson/assertjson_test.go @@ -2818,7 +2818,7 @@ func TestAssertNode_Exists(t *testing.T) { const tokenSecret = "your-256-bit-secret" -func getJWTSecret(token *jwt.Token) (interface{}, error) { +func getJWTSecret(_ *jwt.Token) (interface{}, error) { return []byte(tokenSecret), nil }