Skip to content

Commit 49aadad

Browse files
author
Stein Fletcher
committed
Add matcher for JWTs
1 parent 92ffcb2 commit 49aadad

File tree

3 files changed

+125
-80
lines changed

3 files changed

+125
-80
lines changed

jsonpath_test.go

Lines changed: 20 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package jsonpath
1+
package jsonpath_test
22

33
import (
44
"bytes"
@@ -9,6 +9,8 @@ import (
99

1010
"github.com/steinfletcher/apitest"
1111
"github.com/stretchr/testify/assert"
12+
13+
jsonpath "github.com/steinfletcher/apitest-jsonpath"
1214
)
1315

1416
func TestApiTest_Contains(t *testing.T) {
@@ -26,7 +28,7 @@ func TestApiTest_Contains(t *testing.T) {
2628
Handler(handler).
2729
Get("/hello").
2830
Expect(t).
29-
Assert(Contains(`$.b[? @.key=="c"].value`, "result")).
31+
Assert(jsonpath.Contains(`$.b[? @.key=="c"].value`, "result")).
3032
End()
3133
}
3234

@@ -45,7 +47,7 @@ func TestApiTest_Equal_Numeric(t *testing.T) {
4547
Handler(handler).
4648
Get("/hello").
4749
Expect(t).
48-
Assert(Equal(`$.a`, float64(12345))).
50+
Assert(jsonpath.Equal(`$.a`, float64(12345))).
4951
End()
5052
}
5153

@@ -64,7 +66,7 @@ func TestApiTest_Equal_String(t *testing.T) {
6466
Handler(handler).
6567
Get("/hello").
6668
Expect(t).
67-
Assert(Equal(`$.a`, "12345")).
69+
Assert(jsonpath.Equal(`$.a`, "12345")).
6870
End()
6971
}
7072

@@ -83,60 +85,10 @@ func TestApiTest_Equal_Map(t *testing.T) {
8385
Handler(handler).
8486
Get("/hello").
8587
Expect(t).
86-
Assert(Equal(`$`, map[string]interface{}{"a": "hello", "b": float64(12345)})).
88+
Assert(jsonpath.Equal(`$`, map[string]interface{}{"a": "hello", "b": float64(12345)})).
8789
End()
8890
}
8991

90-
func Test_IncludesElement(t *testing.T) {
91-
list1 := []string{"Foo", "Bar"}
92-
list2 := []int{1, 2}
93-
simpleMap := map[interface{}]interface{}{"Foo": "Bar"}
94-
95-
ok, found := includesElement("Hello World", "World")
96-
assertTrue(t, ok)
97-
assertTrue(t, found)
98-
99-
ok, found = includesElement(list1, "Foo")
100-
assertTrue(t, ok)
101-
assertTrue(t, found)
102-
103-
ok, found = includesElement(list1, "Bar")
104-
assertTrue(t, ok)
105-
assertTrue(t, found)
106-
107-
ok, found = includesElement(list2, 1)
108-
assertTrue(t, ok)
109-
assertTrue(t, found)
110-
111-
ok, found = includesElement(list2, 2)
112-
assertTrue(t, ok)
113-
assertTrue(t, found)
114-
115-
ok, found = includesElement(list1, "Foo!")
116-
assertTrue(t, ok)
117-
assertFalse(t, found)
118-
119-
ok, found = includesElement(list2, 3)
120-
assertTrue(t, ok)
121-
assertFalse(t, found)
122-
123-
ok, found = includesElement(list2, "1")
124-
assertTrue(t, ok)
125-
assertFalse(t, found)
126-
127-
ok, found = includesElement(simpleMap, "Foo")
128-
assertTrue(t, ok)
129-
assertTrue(t, found)
130-
131-
ok, found = includesElement(simpleMap, "Bar")
132-
assertTrue(t, ok)
133-
assertFalse(t, found)
134-
135-
ok, found = includesElement(1433, "1")
136-
assertFalse(t, ok)
137-
assertFalse(t, found)
138-
}
139-
14092
func TestApiTest_Len(t *testing.T) {
14193
handler := http.NewServeMux()
14294
handler.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
@@ -152,8 +104,8 @@ func TestApiTest_Len(t *testing.T) {
152104
Handler(handler).
153105
Get("/hello").
154106
Expect(t).
155-
Assert(Len(`$.a`, 3)).
156-
Assert(Len(`$.b`, 1)).
107+
Assert(jsonpath.Len(`$.a`, 3)).
108+
Assert(jsonpath.Len(`$.b`, 1)).
157109
End()
158110
}
159111

@@ -172,8 +124,8 @@ func TestApiTest_GreaterThan(t *testing.T) {
172124
Handler(handler).
173125
Get("/hello").
174126
Expect(t).
175-
Assert(GreaterThan(`$.a`, 2)).
176-
Assert(GreaterThan(`$.b`, 0)).
127+
Assert(jsonpath.GreaterThan(`$.a`, 2)).
128+
Assert(jsonpath.GreaterThan(`$.b`, 0)).
177129
End()
178130
}
179131

@@ -192,8 +144,8 @@ func TestApiTest_LessThan(t *testing.T) {
192144
Handler(handler).
193145
Get("/hello").
194146
Expect(t).
195-
Assert(LessThan(`$.a`, 4)).
196-
Assert(LessThan(`$.b`, 2)).
147+
Assert(jsonpath.LessThan(`$.a`, 4)).
148+
Assert(jsonpath.LessThan(`$.b`, 2)).
197149
End()
198150
}
199151

@@ -212,8 +164,8 @@ func TestApiTest_Present(t *testing.T) {
212164
Handler(handler).
213165
Get("/hello").
214166
Expect(t).
215-
Assert(Present(`$.a`)).
216-
Assert(NotPresent(`$.password`)).
167+
Assert(jsonpath.Present(`$.a`)).
168+
Assert(jsonpath.NotPresent(`$.password`)).
217169
End()
218170
}
219171

@@ -242,21 +194,21 @@ func TestApiTest_Matches(t *testing.T) {
242194
Handler(handler).
243195
Get("/hello").
244196
Expect(t).
245-
Assert(Matches(testCase[0], testCase[1])).
197+
Assert(jsonpath.Matches(testCase[0], testCase[1])).
246198
End()
247199
})
248200
}
249201
}
250202

251203
func TestApiTest_Matches_FailCompile(t *testing.T) {
252-
willFailToCompile := Matches(`$.b[? @.key=="c"].value`, `\`)
204+
willFailToCompile := jsonpath.Matches(`$.b[? @.key=="c"].value`, `\`)
253205
err := willFailToCompile(nil, nil)
254206

255207
assert.EqualError(t, err, `invalid pattern: '\'`)
256208
}
257209

258210
func TestApiTest_Matches_FailForObject(t *testing.T) {
259-
matcher := Matches(`$.anObject`, `.+`)
211+
matcher := jsonpath.Matches(`$.anObject`, `.+`)
260212

261213
err := matcher(&http.Response{
262214
Body: ioutil.NopCloser(bytes.NewBuffer([]byte(`{"anObject":{"aString":"lol"}}`))),
@@ -266,7 +218,7 @@ func TestApiTest_Matches_FailForObject(t *testing.T) {
266218
}
267219

268220
func TestApiTest_Matches_FailForArray(t *testing.T) {
269-
matcher := Matches(`$.aSlice`, `.+`)
221+
matcher := jsonpath.Matches(`$.aSlice`, `.+`)
270222

271223
err := matcher(&http.Response{
272224
Body: ioutil.NopCloser(bytes.NewBuffer([]byte(`{"aSlice":[1,2,3]}`))),
@@ -276,23 +228,11 @@ func TestApiTest_Matches_FailForArray(t *testing.T) {
276228
}
277229

278230
func TestApiTest_Matches_FailForNilValue(t *testing.T) {
279-
matcher := Matches(`$.nothingHere`, `.+`)
231+
matcher := jsonpath.Matches(`$.nothingHere`, `.+`)
280232

281233
err := matcher(&http.Response{
282234
Body: ioutil.NopCloser(bytes.NewBuffer([]byte(`{"aSlice":[1,2,3]}`))),
283235
}, nil)
284236

285237
assert.EqualError(t, err, "no match for pattern: '$.nothingHere'")
286238
}
287-
288-
func assertTrue(t *testing.T, v bool) {
289-
if !v {
290-
t.Error("\nexpected to be true but was false")
291-
}
292-
}
293-
294-
func assertFalse(t *testing.T, v bool) {
295-
if v {
296-
t.Error("\nexpected to be false but was true")
297-
}
298-
}

jwt.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package jsonpath
2+
3+
import (
4+
"bytes"
5+
"encoding/base64"
6+
"errors"
7+
"fmt"
8+
"net/http"
9+
"strings"
10+
11+
"github.com/steinfletcher/apitest"
12+
)
13+
14+
const (
15+
jwtHeaderIndex = 0
16+
jwtPayloadIndex = 1
17+
)
18+
19+
func JWTHeaderEqual(tokenSelector func(*http.Response) (string, error), expression string, expected interface{}) apitest.Assert {
20+
return jwtEqual(tokenSelector, expression, expected, jwtHeaderIndex)
21+
}
22+
23+
func JWTPayloadEqual(tokenSelector func(*http.Response) (string, error), expression string, expected interface{}) apitest.Assert {
24+
return jwtEqual(tokenSelector, expression, expected, jwtPayloadIndex)
25+
}
26+
27+
func jwtEqual(tokenSelector func(*http.Response) (string, error), expression string, expected interface{}, index int) apitest.Assert {
28+
return func(response *http.Response, request *http.Request) error {
29+
token, err := tokenSelector(response)
30+
if err != nil {
31+
return err
32+
}
33+
34+
parts := strings.Split(token, ".")
35+
if len(parts) != 3 {
36+
splitErr := errors.New("Invalid token: token should contain header, payload and secret")
37+
return splitErr
38+
}
39+
40+
decodedPayload, PayloadErr := base64Decode(parts[index])
41+
if PayloadErr != nil {
42+
return fmt.Errorf("Invalid jwt: %s", PayloadErr.Error())
43+
}
44+
45+
value, err := jsonPath(bytes.NewReader(decodedPayload), expression)
46+
if err != nil {
47+
return err
48+
}
49+
50+
if !objectsAreEqual(value, expected) {
51+
return errors.New(fmt.Sprintf("\"%s\" not equal to \"%s\"", value, expected))
52+
}
53+
54+
return nil
55+
}
56+
}
57+
58+
func base64Decode(src string) ([]byte, error) {
59+
if l := len(src) % 4; l > 0 {
60+
src += strings.Repeat("=", 4-l)
61+
}
62+
63+
decoded, err := base64.URLEncoding.DecodeString(src)
64+
if err != nil {
65+
errMsg := fmt.Errorf("Decoding Error %s", err)
66+
return nil, errMsg
67+
}
68+
return decoded, nil
69+
}

jwt_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package jsonpath_test
2+
3+
import (
4+
"net/http"
5+
"testing"
6+
7+
"github.com/steinfletcher/apitest"
8+
9+
jsonpath "github.com/steinfletcher/apitest-jsonpath"
10+
)
11+
12+
const jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
13+
14+
func TestApiTest_JWT(t *testing.T) {
15+
handler := http.NewServeMux()
16+
handler.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
17+
w.Header().Set("Content-Type", "application/json")
18+
w.Header().Set("Authorization", jwt)
19+
w.WriteHeader(http.StatusOK)
20+
})
21+
22+
apitest.New().
23+
Handler(handler).
24+
Get("/hello").
25+
Expect(t).
26+
Assert(jsonpath.JWTPayloadEqual(fromAuthHeader, `$.name`, "John Doe")).
27+
Assert(jsonpath.JWTPayloadEqual(fromAuthHeader, `$.sub`, "1234567890")).
28+
Assert(jsonpath.JWTPayloadEqual(fromAuthHeader, `$.iat`, float64(1516239022))).
29+
Assert(jsonpath.JWTHeaderEqual(fromAuthHeader, `$.alg`, "HS256")).
30+
Assert(jsonpath.JWTHeaderEqual(fromAuthHeader, `$.typ`, "JWT")).
31+
End()
32+
}
33+
34+
func fromAuthHeader(response *http.Response) (string, error) {
35+
return response.Header.Get("Authorization"), nil
36+
}

0 commit comments

Comments
 (0)