clazz);
18 | }
19 |
--------------------------------------------------------------------------------
/jsonassert/src/main/java/com/toomuchcoding/jsonassert/JsonVerifiable.java:
--------------------------------------------------------------------------------
1 | package com.toomuchcoding.jsonassert;
2 |
3 | /**
4 | * Contract to match a parsed JSON via JSON Path
5 | *
6 | * @author Marcin Grzejszczak
7 | *
8 | * @since 0.1.0
9 | */
10 | public interface JsonVerifiable extends IteratingOverArray, JsonReader {
11 |
12 | /**
13 | * Assertion of a field inside an array. Use it only for assertion and not traversing
14 | */
15 | JsonVerifiable contains(Object value);
16 |
17 | /**
18 | * Field assertion. Adds a JSON Path entry for the given field.
19 | */
20 | JsonVerifiable field(Object value);
21 |
22 | /**
23 | * Field assertions. Traverses through the list of fields and
24 | * adds a JSON Path entry for each one.
25 | */
26 | JsonVerifiable field(String... fields);
27 |
28 | /**
29 | * When you want to assert values in a array with a given name
30 | */
31 | JsonVerifiable array(Object value);
32 |
33 | /**
34 | * When you want to compare values of a field in a nameless array
35 | */
36 | JsonVerifiable arrayField();
37 |
38 | /**
39 | * When in JSON path you iterate over a nameless array
40 | */
41 | JsonVerifiable array();
42 |
43 | /**
44 | * Provides the {@link JsonVerifiable} for the {@code index} element of the array
45 | */
46 | JsonVerifiable elementWithIndex(int index);
47 |
48 | /**
49 | * 0Equality comparison with String
50 | *
51 | * @throws IllegalStateException - if JSON Path is not matched for the parsed JSON
52 | */
53 | JsonVerifiable isEqualTo(String value) throws IllegalStateException;
54 |
55 | /**
56 | * Equality comparison with any object
57 | *
58 | * @throws IllegalStateException - if JSON Path is not matched for the parsed JSON
59 | */
60 | JsonVerifiable isEqualTo(Object value) throws IllegalStateException;
61 |
62 | /**
63 | * Equality comparison with a Number
64 | *
65 | * @throws IllegalStateException - if JSON Path is not matched for the parsed JSON
66 | */
67 | JsonVerifiable isEqualTo(Number value) throws IllegalStateException;
68 |
69 | /**
70 | * Equality comparison to null
71 | *
72 | * @throws IllegalStateException - if JSON Path is not matched for the parsed JSON
73 | */
74 | JsonVerifiable isNull() throws IllegalStateException;
75 |
76 | /**
77 | * Regex matching for strings
78 | *
79 | * @throws IllegalStateException - if JSON Path is not matched for the parsed JSON
80 | */
81 | JsonVerifiable matches(String value) throws IllegalStateException;
82 |
83 | /**
84 | * Equality comparison with a Boolean
85 | *
86 | * @throws IllegalStateException - if JSON Path is not matched for the parsed JSON
87 | */
88 | JsonVerifiable isEqualTo(Boolean value) throws IllegalStateException;
89 |
90 | /**
91 | * Checks if the array is empty
92 | *
93 | * @throws IllegalStateException - if the result of the JSON Path contains any values
94 | */
95 | JsonVerifiable isEmpty() throws IllegalStateException;
96 |
97 | /**
98 | * Checks if instance is the same type
99 | *
100 | * @throws IllegalStateException - if the object from JSON is not of proper type
101 | */
102 | JsonVerifiable isInstanceOf(Class clazz) throws IllegalStateException;
103 |
104 | /**
105 | * Syntactic sugar for checking against an array of primitives
106 | */
107 | JsonVerifiable value();
108 |
109 | /**
110 | * Calling this method will setup the fluent interface to ignore any JSON Path verification
111 | */
112 | JsonVerifiable withoutThrowingException();
113 |
114 | /**
115 | * Returns current JSON Path expression
116 | */
117 | String jsonPath();
118 |
119 | /**
120 | * Checks if the parsed document matches given JSON Path
121 | */
122 | void matchesJsonPath(String jsonPath);
123 |
124 | /**
125 | * Checks if the array is of a given size. Example of usage:
126 | *
127 | * {@code
128 | * String json = '''{ "some_list" : ["name1", "name2"] }'''
129 | * assertThat(json).array("some_list").hasSize(2)
130 | * }
131 | *
132 | */
133 | JsonVerifiable hasSize(int size);
134 |
135 | }
136 |
--------------------------------------------------------------------------------
/jsonassert/src/main/java/com/toomuchcoding/jsonassert/NamelessArrayHavingFieldAssertion.java:
--------------------------------------------------------------------------------
1 | package com.toomuchcoding.jsonassert;
2 |
3 | import com.jayway.jsonpath.DocumentContext;
4 |
5 | import java.util.LinkedList;
6 |
7 | class NamelessArrayHavingFieldAssertion extends FieldAssertion {
8 | protected NamelessArrayHavingFieldAssertion(DocumentContext parsedJson,
9 | LinkedList jsonPathBuffer, Object fieldName, JsonAsserterConfiguration jsonAsserterConfiguration) {
10 | super(parsedJson, jsonPathBuffer, fieldName, jsonAsserterConfiguration);
11 | }
12 |
13 | @Override
14 | public boolean isIteratingOverNamelessArray() {
15 | return true;
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/jsonassert/src/main/java/com/toomuchcoding/jsonassert/ReadyToCheckAsserter.java:
--------------------------------------------------------------------------------
1 | package com.toomuchcoding.jsonassert;
2 |
3 | import com.jayway.jsonpath.DocumentContext;
4 |
5 | import java.util.LinkedList;
6 |
7 | class ReadyToCheckAsserter extends JsonAsserter {
8 |
9 | public ReadyToCheckAsserter(DocumentContext parsedJson, LinkedList jsonPathBuffer,
10 | Object fieldName, JsonAsserterConfiguration jsonAsserterConfiguration) {
11 | super(parsedJson, jsonPathBuffer, fieldName, jsonAsserterConfiguration);
12 | }
13 | }
--------------------------------------------------------------------------------
/jsonassert/src/test/groovy/com/toomuchcoding/jsonassert/JsonAssertionSpec.groovy:
--------------------------------------------------------------------------------
1 | package com.toomuchcoding.jsonassert
2 |
3 | import com.jayway.jsonpath.DocumentContext
4 | import com.jayway.jsonpath.JsonPath
5 | import com.jayway.jsonpath.PathNotFoundException
6 | import net.minidev.json.JSONArray
7 | import spock.lang.Issue
8 | import spock.lang.Shared
9 | import spock.lang.Specification
10 | import spock.lang.Unroll
11 |
12 | import static JsonAssertion.assertThat
13 | import static JsonAssertion.assertThatJson
14 | import static groovy.json.JsonOutput.toJson
15 |
16 | /**
17 | * @author Marcin Grzejszczak
18 | */
19 | class JsonAssertionSpec extends Specification {
20 |
21 | @Shared String json1 = '''
22 | {
23 | "some" : {
24 | "nested" : {
25 | "json" : "with \\"val'ue",
26 | "anothervalue": 4,
27 | "withlist" : [
28 | { "name" :"name1"} , {"name": "name2"}
29 | ]
30 | }
31 | }
32 | }
33 | '''
34 |
35 | @Unroll
36 | def 'should convert a json with a map as root to a map of path to value '() {
37 | expect:
38 | verifiable.jsonPath() == expectedJsonPath
39 | and:
40 | JsonPath.parse(json1).read(expectedJsonPath, JSONArray)
41 | where:
42 | verifiable || expectedJsonPath
43 | assertThat(json1).field("some").field("nested").field("anothervalue").isEqualTo(4) || '''$.some.nested[?(@.anothervalue == 4)]'''
44 | assertThat(json1).field("some").field("nested").field("anothervalue") || '''$.some.nested.anothervalue'''
45 | assertThatJson(json1).field("some").field("nested").field("anothervalue").isEqualTo(4) || '''$.some.nested[?(@.anothervalue == 4)]'''
46 | assertThat(json1).field("some").field("nested").array("withlist").contains("name").isEqualTo("name1") || '''$.some.nested.withlist[*][?(@.name == 'name1')]'''
47 | assertThat(json1).field("some").field("nested").array("withlist").contains("name").isEqualTo("name2") || '''$.some.nested.withlist[*][?(@.name == 'name2')]'''
48 | assertThat(json1).field("some").field("nested").field("json").isEqualTo("with \"val'ue") || '''$.some.nested[?(@.json == 'with "val\\'ue')]'''
49 | assertThat(json1).field("some", "nested", "json").isEqualTo("with \"val'ue") || '''$.some.nested[?(@.json == 'with "val\\'ue')]'''
50 | }
51 |
52 | @Shared String json2 = '''{
53 | "property1": "a",
54 | "property2": "b"
55 | }'''
56 |
57 | @Unroll
58 | def "should generate assertions for simple response body"() {
59 | expect:
60 | verifiable.jsonPath() == expectedJsonPath
61 | and:
62 | JsonPath.parse(json2).read(expectedJsonPath, JSONArray)
63 | where:
64 | verifiable || expectedJsonPath
65 | assertThat(json2).field("property1").isEqualTo("a") || '''$[?(@.property1 == 'a')]'''
66 | assertThat(json2).field("property2").isEqualTo("b") || '''$[?(@.property2 == 'b')]'''
67 | }
68 |
69 | @Shared String json3 = '''{
70 | "property1": "true",
71 | "property2": null,
72 | "property3": false
73 | }'''
74 |
75 | @Unroll
76 | def "should generate assertions for null and boolean values"() {
77 | expect:
78 | verifiable.jsonPath() == expectedJsonPath
79 | and:
80 | JsonPath.parse(json3).read(expectedJsonPath, JSONArray)
81 | where:
82 | verifiable || expectedJsonPath
83 | assertThat(json3).field("property1").isEqualTo("true") || '''$[?(@.property1 == 'true')]'''
84 | assertThat(json3).field("property2").isNull() || '''$[?(@.property2 == null)]'''
85 | assertThat(json3).field("property3").isEqualTo(false) || '''$[?(@.property3 == false)]'''
86 | }
87 |
88 | @Shared Map json4 = [
89 | property1: 'a',
90 | property2: [
91 | [a: 'sth'],
92 | [b: 'sthElse']
93 | ]
94 | ]
95 |
96 | @Unroll
97 | def "should generate assertions for simple response body constructed from map with a list"() {
98 | expect:
99 | verifiable.jsonPath() == expectedJsonPath
100 | and:
101 | JsonPath.parse(json4).read(expectedJsonPath, JSONArray)
102 | where:
103 | verifiable || expectedJsonPath
104 | assertThat(toJson(json4)).field("property1").isEqualTo("a") || '''$[?(@.property1 == 'a')]'''
105 | assertThat(toJson(json4)).array("property2").contains("a").isEqualTo("sth") || '''$.property2[*][?(@.a == 'sth')]'''
106 | assertThat(toJson(json4)).array("property2").contains("b").isEqualTo("sthElse") || '''$.property2[*][?(@.b == 'sthElse')]'''
107 | }
108 |
109 | @Shared Map json5 = [
110 | property: [
111 | 14: 0.0,
112 | 7 : 0.0
113 | ]
114 | ]
115 |
116 | @Unroll
117 | def "should generate assertions for a response body containing map with integers as keys"() {
118 | expect:
119 | verifiable.jsonPath() == expectedJsonPath
120 | and:
121 | JsonPath.parse(toJson(json5)).read(expectedJsonPath, JSONArray)
122 | where:
123 | verifiable || expectedJsonPath
124 | assertThat(toJson(json5)).field("property").field(7).isEqualTo(0.0) || '''$.property[?(@.7 == 0.0)]'''
125 | assertThat(toJson(json5)).field("property").field(14).isEqualTo(0.0) || '''$.property[?(@.14 == 0.0)]'''
126 | }
127 |
128 | @Shared String json6 = '''[
129 | {
130 | "property1": "a"
131 | },
132 | {
133 | "property2": "b"
134 | }]'''
135 |
136 | @Unroll
137 | def "should generate assertions for array in response body"() {
138 | expect:
139 | verifiable.jsonPath() == expectedJsonPath
140 | and:
141 | JsonPath.parse(json6).read(expectedJsonPath, JSONArray)
142 | where:
143 | verifiable || expectedJsonPath
144 | assertThat(json6).array().contains("property1").isEqualTo("a") || '''$[*][?(@.property1 == 'a')]'''
145 | assertThat(json6).array().contains("property2").isEqualTo("b") || '''$[*][?(@.property2 == 'b')]'''
146 | }
147 |
148 | @Shared String json7 = '''{
149 | "property1": [
150 | { "property2": "test1"},
151 | { "property3": "test2"}
152 | ]
153 | }'''
154 |
155 | @Unroll
156 | def "should generate assertions for array inside response body element"() {
157 | expect:
158 | verifiable.jsonPath() == expectedJsonPath
159 | and:
160 | JsonPath.parse(json7).read(expectedJsonPath, JSONArray)
161 | where:
162 | verifiable || expectedJsonPath
163 | assertThat(json7).array("property1").contains("property2").isEqualTo("test1") || '''$.property1[*][?(@.property2 == 'test1')]'''
164 | assertThat(json7).array("property1").contains("property3").isEqualTo("test2") || '''$.property1[*][?(@.property3 == 'test2')]'''
165 | }
166 |
167 | @Shared String json8 = """{
168 | "property1": "a",
169 | "property2": {"property3": "b"}
170 | }"""
171 |
172 | def "should generate assertions for nested objects in response body"() {
173 | expect:
174 | verifiable.jsonPath() == expectedJsonPath
175 | and:
176 | JsonPath.parse(json8).read(expectedJsonPath, JSONArray)
177 | where:
178 | verifiable || expectedJsonPath
179 | assertThat(json8).field("property2").field("property3").isEqualTo("b") || '''$.property2[?(@.property3 == 'b')]'''
180 | assertThat(json8).field("property1").isEqualTo("a") || '''$[?(@.property1 == 'a')]'''
181 | }
182 |
183 | @Shared Map json9 = [
184 | property1: "a",
185 | property2: 123
186 | ]
187 |
188 | @Unroll
189 | def "should generate regex assertions for map objects in response body"() {
190 | expect:
191 | verifiable.jsonPath() == expectedJsonPath
192 | and:
193 | JsonPath.parse(json9).read(expectedJsonPath, JSONArray)
194 | where:
195 | verifiable || expectedJsonPath
196 | assertThat(toJson(json9)).field("property2").matches("[0-9]{3}") || '''$[?(@.property2 =~ /[0-9]{3}/)]'''
197 | assertThat(toJson(json9)).field("property1").isEqualTo("a") || '''$[?(@.property1 == 'a')]'''
198 | }
199 |
200 | def "should generate escaped regex assertions for string objects in response body"() {
201 | given:
202 | Map json = [
203 | property2: 123123
204 | ]
205 | expect:
206 | def verifiable = assertThat(toJson(json)).field("property2").matches("\\d+")
207 | verifiable.jsonPath() == '''$[?(@.property2 =~ /\\d+/)]'''
208 | and:
209 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
210 | }
211 |
212 | @Shared Map json10 = [
213 | errors: [
214 | [property: "bank_account_number",
215 | message: "incorrect_format"]
216 | ]
217 | ]
218 |
219 | @Unroll
220 | def "should work with more complex stuff and jsonpaths"() {
221 | expect:
222 | verifiable.jsonPath() == expectedJsonPath
223 | and:
224 | JsonPath.parse(json10).read(expectedJsonPath, JSONArray)
225 | where:
226 | verifiable || expectedJsonPath
227 | assertThat(toJson(json10)).array("errors").contains("property").isEqualTo("bank_account_number") || '''$.errors[*][?(@.property == 'bank_account_number')]'''
228 | assertThat(toJson(json10)).array("errors").contains("message").isEqualTo("incorrect_format") || '''$.errors[*][?(@.message == 'incorrect_format')]'''
229 | }
230 |
231 | @Shared String json11 = '''
232 | [{
233 | "place":
234 | {
235 | "bounding_box":
236 | {
237 | "coordinates":
238 | [[
239 | [-77.119759,38.995548],
240 | [-76.909393,38.791645]
241 | ]]
242 | }
243 | }
244 | }]
245 | '''
246 |
247 | @Unroll
248 | def "should manage to parse a triple array"() {
249 | expect:
250 | verifiable.jsonPath() == expectedJsonPath
251 | and:
252 | JsonPath.parse(json11).read(expectedJsonPath, JSONArray)
253 | where:
254 | verifiable || expectedJsonPath
255 | assertThat(json11).array().field("place").field("bounding_box").array("coordinates").array().array().arrayField().contains(38.995548).value() || '''$[*].place.bounding_box.coordinates[*][*][?(@ == 38.995548)]'''
256 | assertThat(json11).array().field("place").field("bounding_box").array("coordinates").array().array().arrayField().contains(-77.119759).value() || '''$[*].place.bounding_box.coordinates[*][*][?(@ == -77.119759)]'''
257 | assertThat(json11).array().field("place").field("bounding_box").array("coordinates").array().array().arrayField().contains(-76.909393).value() || '''$[*].place.bounding_box.coordinates[*][*][?(@ == -76.909393)]'''
258 | assertThat(json11).array().field("place").field("bounding_box").array("coordinates").array().array().arrayField().contains(38.791645).value() || '''$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]'''
259 |
260 | }
261 |
262 | @Shared String json12 = '''
263 | [{
264 | "place":
265 | {
266 | "bounding_box":
267 | {
268 | "coordinates":
269 | [[[
270 | [-77.119759,38.995548],
271 | [-76.909393,38.791645]
272 | ]]]
273 | }
274 | }
275 | }]
276 | '''
277 |
278 | @Unroll
279 | def "should manage to parse a quadriple array"() {
280 | expect:
281 | verifiable.jsonPath() == expectedJsonPath
282 | and:
283 | JsonPath.parse(json12).read(expectedJsonPath, JSONArray)
284 | where:
285 | verifiable || expectedJsonPath
286 | assertThat(json12).array().field("place").field("bounding_box").array("coordinates").array().array().array().arrayField().contains(38.995548).value() || '''$[*].place.bounding_box.coordinates[*][*][*][?(@ == 38.995548)]'''
287 | assertThat(json12).array().field("place").field("bounding_box").array("coordinates").array().array().array().arrayField().contains(-77.119759).value() || '''$[*].place.bounding_box.coordinates[*][*][*][?(@ == -77.119759)]'''
288 | assertThat(json12).array().field("place").field("bounding_box").array("coordinates").array().array().array().arrayField().contains(-76.909393).value() || '''$[*].place.bounding_box.coordinates[*][*][*][?(@ == -76.909393)]'''
289 | assertThat(json12).array().field("place").field("bounding_box").array("coordinates").array().array().array().arrayField().contains(38.791645).value() || '''$[*].place.bounding_box.coordinates[*][*][*][?(@ == 38.791645)]'''
290 |
291 | }
292 |
293 | @Shared String jsonArrayInArray= '''
294 | {
295 | "coordinates":
296 | [
297 | [-77.119759,38.995548],
298 | [-76.909393,38.791645]
299 | ]
300 | }
301 | }
302 | '''
303 |
304 | @Unroll
305 | def "should manage to parse array in array"() {
306 | expect:
307 | verifiable.jsonPath() == expectedJsonPath
308 | and:
309 | JsonPath.parse(jsonArrayInArray).read(expectedJsonPath, JSONArray)
310 | where:
311 | verifiable || expectedJsonPath
312 | assertThat(jsonArrayInArray).array("coordinates").array().arrayField().contains(38.995548).value() || '''$.coordinates[*][?(@ == 38.995548)]'''
313 | assertThat(jsonArrayInArray).array("coordinates").array().arrayField().contains(-77.119759).value() || '''$.coordinates[*][?(@ == -77.119759)]'''
314 | assertThat(jsonArrayInArray).array("coordinates").array().arrayField().contains(-76.909393).value() || '''$.coordinates[*][?(@ == -76.909393)]'''
315 | assertThat(jsonArrayInArray).array("coordinates").array().arrayField().contains(38.791645).value() || '''$.coordinates[*][?(@ == 38.791645)]'''
316 | }
317 |
318 | @Unroll
319 | def 'should convert a json with list as root to a map of path to value'() {
320 | expect:
321 | assertThat(json).array().field("some").field("nested").field("json").isEqualTo("with value").jsonPath() == '''$[*].some.nested[?(@.json == 'with value')]'''
322 | assertThat(json).array().field("some").field("nested").field("anothervalue").isEqualTo(4).jsonPath() == '''$[*].some.nested[?(@.anothervalue == 4)]'''
323 | assertThat(json).array().field("some").field("nested").array("withlist").contains("name").isEqualTo("name1").jsonPath() == '''$[*].some.nested.withlist[*][?(@.name == 'name1')]'''
324 | assertThat(json).array().field("some").field("nested").array("withlist").contains("name").isEqualTo("name2").jsonPath() == '''$[*].some.nested.withlist[*][?(@.name == 'name2')]'''
325 | assertThat(json).array().field("some").field("nested").array("withlist").field("anothernested").field("name").isEqualTo("name3").jsonPath() == '''$[*].some.nested.withlist[*].anothernested[?(@.name == 'name3')]'''
326 | where:
327 | json << [
328 | '''
329 | [ {
330 | "some" : {
331 | "nested" : {
332 | "json" : "with value",
333 | "anothervalue": 4,
334 | "withlist" : [
335 | { "name" :"name1"} , {"name": "name2"}, {"anothernested": { "name": "name3"} }
336 | ]
337 | }
338 | }
339 | },
340 | {
341 | "someother" : {
342 | "nested" : {
343 | "json" : "with value",
344 | "anothervalue": 4,
345 | "withlist" : [
346 | { "name" :"name1"} , {"name": "name2"}
347 | ]
348 | }
349 | }
350 | }
351 | ]
352 | ''',
353 | '''
354 | [{
355 | "someother" : {
356 | "nested" : {
357 | "json" : "with value",
358 | "anothervalue": 4,
359 | "withlist" : [
360 | { "name" :"name1"} , {"name": "name2"}
361 | ]
362 | }
363 | }
364 | },
365 | {
366 | "some" : {
367 | "nested" : {
368 | "json" : "with value",
369 | "anothervalue": 4,
370 | "withlist" : [
371 | {"name": "name2"}, {"anothernested": { "name": "name3"} }, { "name" :"name1"}
372 | ]
373 | }
374 | }
375 | }
376 | ]''']
377 | }
378 |
379 | def "should run json path when provided manually"() {
380 | given:
381 | String json = """{
382 | "property1": "a",
383 | "property2": {"property3": "b"}
384 | }"""
385 | and:
386 | String jsonPath = '''$[?(@.property1 == 'a')]'''
387 | expect:
388 | assertThat(json).matchesJsonPath(jsonPath)
389 | and:
390 | JsonPath.parse(json).read(jsonPath, JSONArray)
391 | }
392 |
393 | def "should throw exception when json path is not matched"() {
394 | given:
395 | String json = """{
396 | "property1": "a",
397 | "property2": {"property3": "b"}
398 | }"""
399 | and:
400 | String jsonPath = '''$[?(@.property1 == 'c')]'''
401 | when:
402 | assertThat(json).matchesJsonPath(jsonPath)
403 | then:
404 | IllegalStateException illegalStateException = thrown(IllegalStateException)
405 | illegalStateException.message.contains("Parsed JSON")
406 | illegalStateException.message.contains("doesn't match")
407 | }
408 |
409 | def "should not throw exception when json path is not matched and system prop overrides the check"() {
410 | given:
411 | String json = """{
412 | "property1": "a",
413 | "property2": {"property3": "b"}
414 | }"""
415 | and:
416 | String jsonPath = '''$[?(@.property1 == 'c')]'''
417 | when:
418 | assertThat(json).withoutThrowingException().matchesJsonPath(jsonPath)
419 | then:
420 | noExceptionThrown()
421 | }
422 |
423 | def "should generate escaped regex assertions for boolean objects in response body"() {
424 | given:
425 | Map json = [
426 | property2: true
427 | ]
428 | expect:
429 | def verifiable = assertThat(toJson(json)).field("property2").matches('true|false')
430 | verifiable.jsonPath() == '''$[?(@.property2 =~ /true|false/)]'''
431 | and:
432 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
433 | }
434 |
435 | def "should generate escaped regex assertions for numbers objects in response body"() {
436 | given:
437 | Map json = [
438 | property2: 50
439 | ]
440 | expect:
441 | def verifiable = assertThat(toJson(json)).field("property2").matches('[0-9]{2}')
442 | verifiable.jsonPath() == '''$[?(@.property2 =~ /[0-9]{2}/)]'''
443 | and:
444 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
445 | }
446 |
447 | def "should escape regular expression properly"() {
448 | given:
449 | String json = """
450 | {
451 | "path" : "/api/12",
452 | "correlationId" : 123456
453 | }
454 | """
455 | expect:
456 | DocumentContext parsedJson = JsonPath.parse(json)
457 | def verifiable = assertThatJson(parsedJson).field("path").matches("^/api/[0-9]{2}\$")
458 | verifiable.jsonPath() == '''$[?(@.path =~ /^\\/api\\/[0-9]{2}$/)]'''
459 | and:
460 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
461 | }
462 |
463 | @Issue("Accurest#193")
464 | def "should escape single quotes in a quoted string"() {
465 | given:
466 | String json = """
467 | {
468 | "text" : "text with 'quotes' inside"
469 | }
470 | """
471 | expect:
472 | DocumentContext parsedJson = JsonPath.parse(json)
473 | def verifiable = assertThatJson(parsedJson).field("text").isEqualTo("text with 'quotes' inside")
474 | verifiable.jsonPath() == '''$[?(@.text == 'text with \\'quotes\\' inside')]'''
475 | and:
476 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
477 | }
478 |
479 | @Issue("Accurest#193")
480 | def "should escape double quotes in a quoted string"() {
481 | given:
482 | String json = """
483 | {
484 | "text" : "text with \\"quotes\\" inside"
485 | }
486 | """
487 | expect:
488 | DocumentContext parsedJson = JsonPath.parse(json)
489 | def verifiable = assertThatJson(parsedJson).field("text").isEqualTo('''text with "quotes" inside''')
490 | verifiable.jsonPath() == '''$[?(@.text == 'text with "quotes" inside')]'''
491 | and:
492 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
493 | }
494 |
495 | def 'should resolve the value of JSON via JSON Path'() {
496 | given:
497 | String json =
498 | '''
499 | [ {
500 | "some" : {
501 | "nested" : {
502 | "json" : "with value",
503 | "anothervalue": 4,
504 | "withlist" : [
505 | { "name" :"name1"} ,
506 | {"name": "name2"},
507 | {"anothernested": { "name": "name3"} }
508 | ]
509 | }
510 | }
511 | },
512 | {
513 | "someother" : {
514 | "nested" : {
515 | "json" : true,
516 | "anothervalue": 4,
517 | "withlist" : [
518 | { "name" :"name1"} , {"name": "name2"}
519 | ],
520 | "withlist2" : [
521 | "a", "b"
522 | ]
523 | }
524 | }
525 | }
526 | ]
527 | '''
528 | expect:
529 | com.toomuchcoding.jsonassert.JsonPath.builder(json).array().field("some").field("nested").field("json").read(String) == 'with value'
530 | com.toomuchcoding.jsonassert.JsonPath.builder(json).array().field("some").field("nested").field("anothervalue").read(Integer) == 4
531 | assertThat(json).array().field("some").field("nested").array("withlist").field("name").read(List) == ['name1', 'name2']
532 | assertThat(json).array().field("someother").field("nested").array("withlist2").read(List) == ['a', 'b']
533 | assertThat(json).array().field("someother").field("nested").field("json").read(Boolean) == true
534 | }
535 |
536 | def 'should assert json with only top list elements'() {
537 | given:
538 | String json = '''["Java", "Java8", "Spring", "SpringBoot", "Stream"]'''
539 | expect:
540 | assertThatJson(json).arrayField().contains("Java8").value()
541 | assertThatJson(json).arrayField().contains("Spring").value()
542 | assertThatJson(json).arrayField().contains("Java").value()
543 | assertThatJson(json).arrayField().contains("Stream").value()
544 | assertThatJson(json).arrayField().contains("SpringBoot").value()
545 | }
546 |
547 | @Issue("#9")
548 | def 'should match array containing an array of primitives'() {
549 | given:
550 | String json = '''{"first_name":"existing",
551 | "partners":[
552 | { "role":"AGENT",
553 | "payment_methods":[ "BANK", "CASH" ]
554 | }
555 | ]
556 | }'''
557 | expect:
558 | def verifiable = assertThatJson(json).array("partners").array("payment_methods").arrayField().isEqualTo("BANK").value()
559 | verifiable.jsonPath() == '''$.partners[*].payment_methods[?(@ == 'BANK')]'''
560 | and:
561 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
562 | }
563 |
564 | @Issue("#9")
565 | def 'should match pattern in array'() {
566 | given:
567 | String json = '''{ "authorities": ["ROLE_ADMIN"] }'''
568 | expect:
569 | def verifiable = assertThatJson(json).array("authorities").arrayField().matches("^[a-zA-Z0-9_\\- ]+\$").value()
570 | verifiable.jsonPath() == '''$.authorities[?(@ =~ /^[a-zA-Z0-9_\\- ]+$/)]'''
571 | and:
572 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
573 | }
574 |
575 | @Issue("#10")
576 | def 'should manage to parse array with string values'() {
577 | given:
578 | String json = '''{ "some_list" : ["name1", "name2"] }'''
579 | expect:
580 | def v1 = assertThat(JsonPath.parse(json)).array("some_list").arrayField().isEqualTo("name1")
581 | def v2 = assertThat(JsonPath.parse(json)).array("some_list").arrayField().isEqualTo("name2")
582 | and:
583 | v1.jsonPath() == '''$.some_list[?(@ == 'name1')]'''
584 | v2.jsonPath() == '''$.some_list[?(@ == 'name2')]'''
585 | and:
586 | JsonPath.parse(json).read(v1.jsonPath(), JSONArray)
587 | JsonPath.parse(json).read(v2.jsonPath(), JSONArray)
588 | }
589 |
590 | def 'should parse an array of arrays that are root elements'() {
591 | given:
592 | String json = '''[["Programming", "Java"], ["Programming", "Java", "Spring", "Boot"]]'''
593 | expect:
594 | def v1 = assertThatJson(JsonPath.parse(json)).array().arrayField().isEqualTo("Java").value()
595 | and:
596 | v1.jsonPath() == '''$[*][?(@ == 'Java')]'''
597 | and:
598 | JsonPath.parse(json).read(v1.jsonPath(), JSONArray)
599 | }
600 |
601 | @Issue('#11')
602 | def 'should allow to check array size'() {
603 | given:
604 | String json = '''{ "some_list" : ["name1", "name2"] }'''
605 | expect:
606 | assertThat(json).array("some_list").hasSize(2)
607 | when:
608 | assertThat(json).array("some_list").hasSize(5)
609 | then:
610 | def ex = thrown(RuntimeException)
611 | ex instanceof IllegalStateException
612 | ex.message == '''Parsed JSON <{"some_list":["name1","name2"]}> doesn't have the size <5> for JSON path <$.some_list[*]>. The size is <2>'''
613 | }
614 |
615 | @Issue('#11')
616 | def 'should allow to check size of root array'() {
617 | given:
618 | String json = '''["name1", "name2"]'''
619 | expect:
620 | assertThat(json).hasSize(2)
621 | when:
622 | assertThat(json).hasSize(5)
623 | then:
624 | def ex = thrown(RuntimeException)
625 | ex instanceof IllegalStateException
626 | ex.message == '''Parsed JSON <["name1","name2"]> doesn't have the size <5> for JSON path <$>. The size is <2>'''
627 | }
628 |
629 | @Issue('#11')
630 | def 'should allow to check size of a nested array'() {
631 | given:
632 | String json =
633 | '''
634 | [ {
635 | "some" : {
636 | "nested" : {
637 | "json" : "with value",
638 | "anothervalue": 4,
639 | "withlist" : [
640 | { "name" :"name1"} ,
641 | {"name": "name2"},
642 | {"anothernested": { "name": "name3"} }
643 | ]
644 | }
645 | }
646 | },
647 | {
648 | "someother" : {
649 | "nested" : {
650 | "json" : true,
651 | "anothervalue": 4,
652 | "withlist" : [
653 | { "name" :"name1"} , {"name": "name2"}
654 | ],
655 | "withlist2" : [
656 | "a", "b"
657 | ]
658 | }
659 | }
660 | }
661 | ]'''
662 | expect:
663 | assertThat(json).array().field("someother").field("nested").array("withlist2").hasSize(2)
664 | when:
665 | assertThat(json).array().field("someother").field("nested").array("withlist2").hasSize(5)
666 | then:
667 | def ex = thrown(RuntimeException)
668 | ex instanceof IllegalStateException
669 | ex.message == '''Parsed JSON <[{"some":{"nested":{"json":"with value","anothervalue":4,"withlist":[{"name":"name1"},{"name":"name2"},{"anothernested":{"name":"name3"}}]}}},{"someother":{"nested":{"json":true,"anothervalue":4,"withlist":[{"name":"name1"},{"name":"name2"}],"withlist2":["a","b"]}}}]> doesn't have the size <5> for JSON path <$[*].someother.nested.withlist2[*]>. The size is <2>'''
670 | }
671 |
672 | @Issue('#11')
673 | def 'should allow to check size of a named array'() {
674 | given:
675 | def json = [
676 | property1: 'a',
677 | property2: [
678 | [a: 'sth'],
679 | [b: 'sthElse']
680 | ]
681 | ]
682 | expect:
683 | assertThat(toJson(json)).array("property2").hasSize(2)
684 | when:
685 | assertThat(toJson(json)).array("property2").hasSize(5)
686 | then:
687 | def ex = thrown(RuntimeException)
688 | ex instanceof IllegalStateException
689 | ex.message == '''Parsed JSON <{"property1":"a","property2":[{"a":"sth"},{"b":"sthElse"}]}> doesn't have the size <5> for JSON path <$.property2[*]>. The size is <2>'''
690 | }
691 |
692 | @Issue('#11')
693 | def 'should allow to check size of two nameless arrays'() {
694 | given:
695 | String json = '''[["Programming", "Java"], ["Programming", "Java", "Spring", "Boot"], ["Programming", "Java", "Spring", "Boot", "Master"]]'''
696 | expect:
697 | assertThat(json).hasSize(3)
698 | assertThat(json).elementWithIndex(0).hasSize(2)
699 | assertThat(json).elementWithIndex(1).hasSize(4)
700 | when:
701 | assertThat(json).array().hasSize(4)
702 | then:
703 | def ex = thrown(RuntimeException)
704 | ex instanceof IllegalStateException
705 | ex.message == '''Parsed JSON <[["Programming","Java"],["Programming","Java","Spring","Boot"],["Programming","Java","Spring","Boot","Master"]]> doesn't have the size <4> for JSON path <$[*]>. The size is <3>'''
706 | }
707 |
708 | @Issue('#11')
709 | def 'should allow to check size of two nameless arrays in a nameless array'() {
710 | given:
711 | String json = '''[[["Programming", "Java"], ["Programming", "Java", "Spring", "Boot"]]]'''
712 | expect:
713 | assertThat(json).hasSize(1)
714 | assertThat(json).elementWithIndex(0).elementWithIndex(0).hasSize(2)
715 | assertThat(json).elementWithIndex(0).elementWithIndex(1).hasSize(4)
716 | when:
717 | assertThat(json).elementWithIndex(0).elementWithIndex(1).hasSize(5)
718 | then:
719 | def ex = thrown(RuntimeException)
720 | ex instanceof IllegalStateException
721 | ex.message == '''Parsed JSON <[[["Programming","Java"],["Programming","Java","Spring","Boot"]]]> doesn't have the size <5> for JSON path <$[0][1]>. The size is <4>'''
722 | }
723 |
724 | @Issue('#11')
725 | def 'should allow to check array size of nameless array'() {
726 | given:
727 | String json = '''{ "coordinates" : [[
728 | ["name1", "name2"],
729 | ["name3", "name4"]
730 | ]] }'''
731 | expect:
732 | assertThat(json).array("coordinates").array().hasSize(2)
733 | when:
734 | assertThat(json).array("coordinates").array().hasSize(5)
735 | then:
736 | def ex = thrown(RuntimeException)
737 | ex instanceof IllegalStateException
738 | ex.message == '''Parsed JSON <{"coordinates":[[["name1","name2"],["name3","name4"]]]}> doesn't have the size <5> for JSON path <$.coordinates[*][*]>. The size is <2>'''
739 | }
740 |
741 | @Unroll
742 | def 'should fail on non existent path'() {
743 | when:
744 | assertThat(json instanceof Map ? toJson(json) : json).field("non").field("existant").field("field").isEqualTo("imaginary value")
745 | then:
746 | def ex = thrown(RuntimeException)
747 | ex.cause instanceof PathNotFoundException
748 | where:
749 | json << [ json1, json2, json3, json4, json5, json6, json7, json8, json9, json10, json11 ]
750 | }
751 |
752 | @Issue('#14')
753 | def 'should allow to check if size is empty'() {
754 | given:
755 | String json = '''{ "coordinates" : [], "foo": ["bar", "baz"] }'''
756 | expect:
757 | assertThat(json).array("coordinates").isEmpty()
758 | when:
759 | assertThat(json).array("foo").isEmpty()
760 | then:
761 | def ex = thrown(RuntimeException)
762 | ex instanceof IllegalStateException
763 | ex.message == '''Parsed JSON [{"coordinates":[],"foo":["bar","baz"]}] with the JSON path [$.foo[*]] is not empty!'''
764 | }
765 |
766 | @Issue('#17')
767 | def 'should ignore exception on empty check'() {
768 | given:
769 | String json = '''{ "coordinates" : [], "foo": ["bar", "baz"] }'''
770 | when:
771 | assertThat(json).withoutThrowingException().array("foo").isEmpty()
772 | then:
773 | noExceptionThrown()
774 | }
775 |
776 | @Issue('#16')
777 | def 'should throw exception when an empty array is returned'() {
778 | given:
779 | String json = '''{}'''
780 | when:
781 | assertThatJson(json).field("doesNotExist").matches("[\\p{L}]*")
782 | then:
783 | def ex = thrown(RuntimeException)
784 | ex instanceof IllegalStateException
785 | ex.message == '''Parsed JSON [{}] doesn't match the JSON path [$[?(@.doesNotExist =~ /[\\p{L}]*/)]]'''
786 | when:
787 | assertThatJson(json).array("c").matches("[\\p{L}]*")
788 | then:
789 | ex = thrown(RuntimeException)
790 | ex instanceof IllegalStateException
791 | ex.message == '''Parsed JSON [{}] doesn't match the JSON path [$[?(@.c =~ /[\\p{L}]*/)]]'''
792 | }
793 |
794 | @Issue('#18')
795 | def 'should read types of objects'() {
796 | given:
797 | String json = '''{ "foo": 46 }'''
798 | when:
799 | assertThatJson(json).field("foo").isInstanceOf(Number)
800 | then:
801 | noExceptionThrown()
802 | when:
803 | assertThatJson(json).field("foo").isInstanceOf(String)
804 | then:
805 | RuntimeException ex = thrown(RuntimeException)
806 | ex instanceof IllegalStateException
807 | ex.message == '''For JSON path [$.foo] instance of [Integer] is not assignable from [String]'''
808 | }
809 |
810 | @Issue('#18')
811 | def 'should read big numbers'() {
812 | given:
813 | String json = '''{ "largeNum": 55534673.56, "bigInt": 2147483647, "decimals": 0.1287361923123}'''
814 | when:
815 | assertThatJson(json).field("largeNum").isEqualTo(55534673.56 as Double)
816 | then:
817 | noExceptionThrown()
818 | when:
819 | assertThatJson(json).field("bigInt").isEqualTo(Integer.MAX_VALUE as Integer)
820 | then:
821 | noExceptionThrown()
822 | when:
823 | assertThatJson(json).field("decimals").isEqualTo(0.1287361923123 as Double)
824 | then:
825 | noExceptionThrown()
826 | }
827 |
828 | @Issue('#28')
829 | def 'should match {} as empty'() {
830 | given:
831 | String json = '''{ "field1": {}, field2: [] }}'''
832 | when:
833 | assertThatJson(json).field("field1").isEmpty()
834 | then:
835 | noExceptionThrown()
836 | when:
837 | assertThatJson(json).field("field2").isEmpty()
838 | then:
839 | noExceptionThrown()
840 | }
841 |
842 | @Issue('#31')
843 | def 'should work with scientific notation'() {
844 | given:
845 | String json = '''{ "n": 1.12E-12}'''
846 | when:
847 | assertThatJson(json).field("n").isEqualTo(1.12E-12)
848 | then:
849 | noExceptionThrown()
850 | }
851 |
852 | @Issue('#57')
853 | def 'should work with matchers'() {
854 | given:
855 | String json = '''{ "value": -1}'''
856 | when:
857 | assertThatJson(json).field("['value']").matches("-?(\\d+)")
858 | then:
859 | noExceptionThrown()
860 | }
861 |
862 | }
863 |
--------------------------------------------------------------------------------
/jsonassert/src/test/groovy/com/toomuchcoding/jsonassert/JsonPathSpec.groovy:
--------------------------------------------------------------------------------
1 | package com.toomuchcoding.jsonassert
2 |
3 | import spock.lang.Specification
4 |
5 | /**
6 | * @author Marcin Grzejszczak
7 | */
8 | class JsonPathSpec extends Specification {
9 |
10 | def "should generate proper JSON paths"() {
11 | expect:
12 | jsonPath == expectedJsonPath
13 | where:
14 | jsonPath || expectedJsonPath
15 | JsonPath.builder().field("some").field("nested").field("anothervalue").isEqualTo(4).jsonPath() || '''$.some.nested[?(@.anothervalue == 4)]'''
16 | JsonPath.builder().field("some").field("nested").field("anothervalue").isEqualTo(4).jsonPath() || '''$.some.nested[?(@.anothervalue == 4)]'''
17 | JsonPath.builder().field("some").field("nested").array("withlist").contains("name").isEqualTo("name1").jsonPath() || '''$.some.nested.withlist[*][?(@.name == 'name1')]'''
18 | JsonPath.builder().field("some").field("nested").array("withlist").contains("name").isEqualTo("name2").jsonPath() || '''$.some.nested.withlist[*][?(@.name == 'name2')]'''
19 | JsonPath.builder().field("some").field("nested").field("json").isEqualTo("with \"val'ue").jsonPath() || '''$.some.nested[?(@.json == 'with "val\\'ue')]'''
20 | JsonPath.builder().field("some", "nested", "json").isEqualTo("with \"val'ue").jsonPath() || '''$.some.nested[?(@.json == 'with "val\\'ue')]'''
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /usr/local/etc/mavenrc ] ; then
40 | . /usr/local/etc/mavenrc
41 | fi
42 |
43 | if [ -f /etc/mavenrc ] ; then
44 | . /etc/mavenrc
45 | fi
46 |
47 | if [ -f "$HOME/.mavenrc" ] ; then
48 | . "$HOME/.mavenrc"
49 | fi
50 |
51 | fi
52 |
53 | # OS specific support. $var _must_ be set to either true or false.
54 | cygwin=false;
55 | darwin=false;
56 | mingw=false
57 | case "`uname`" in
58 | CYGWIN*) cygwin=true ;;
59 | MINGW*) mingw=true;;
60 | Darwin*) darwin=true
61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
63 | if [ -z "$JAVA_HOME" ]; then
64 | if [ -x "/usr/libexec/java_home" ]; then
65 | export JAVA_HOME="`/usr/libexec/java_home`"
66 | else
67 | export JAVA_HOME="/Library/Java/Home"
68 | fi
69 | fi
70 | ;;
71 | esac
72 |
73 | if [ -z "$JAVA_HOME" ] ; then
74 | if [ -r /etc/gentoo-release ] ; then
75 | JAVA_HOME=`java-config --jre-home`
76 | fi
77 | fi
78 |
79 | if [ -z "$M2_HOME" ] ; then
80 | ## resolve links - $0 may be a link to maven's home
81 | PRG="$0"
82 |
83 | # need this for relative symlinks
84 | while [ -h "$PRG" ] ; do
85 | ls=`ls -ld "$PRG"`
86 | link=`expr "$ls" : '.*-> \(.*\)$'`
87 | if expr "$link" : '/.*' > /dev/null; then
88 | PRG="$link"
89 | else
90 | PRG="`dirname "$PRG"`/$link"
91 | fi
92 | done
93 |
94 | saveddir=`pwd`
95 |
96 | M2_HOME=`dirname "$PRG"`/..
97 |
98 | # make it fully qualified
99 | M2_HOME=`cd "$M2_HOME" && pwd`
100 |
101 | cd "$saveddir"
102 | # echo Using m2 at $M2_HOME
103 | fi
104 |
105 | # For Cygwin, ensure paths are in UNIX format before anything is touched
106 | if $cygwin ; then
107 | [ -n "$M2_HOME" ] &&
108 | M2_HOME=`cygpath --unix "$M2_HOME"`
109 | [ -n "$JAVA_HOME" ] &&
110 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
111 | [ -n "$CLASSPATH" ] &&
112 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
113 | fi
114 |
115 | # For Mingw, ensure paths are in UNIX format before anything is touched
116 | if $mingw ; then
117 | [ -n "$M2_HOME" ] &&
118 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
119 | [ -n "$JAVA_HOME" ] &&
120 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
121 | fi
122 |
123 | if [ -z "$JAVA_HOME" ]; then
124 | javaExecutable="`which javac`"
125 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
126 | # readlink(1) is not available as standard on Solaris 10.
127 | readLink=`which readlink`
128 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
129 | if $darwin ; then
130 | javaHome="`dirname \"$javaExecutable\"`"
131 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
132 | else
133 | javaExecutable="`readlink -f \"$javaExecutable\"`"
134 | fi
135 | javaHome="`dirname \"$javaExecutable\"`"
136 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
137 | JAVA_HOME="$javaHome"
138 | export JAVA_HOME
139 | fi
140 | fi
141 | fi
142 |
143 | if [ -z "$JAVACMD" ] ; then
144 | if [ -n "$JAVA_HOME" ] ; then
145 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
146 | # IBM's JDK on AIX uses strange locations for the executables
147 | JAVACMD="$JAVA_HOME/jre/sh/java"
148 | else
149 | JAVACMD="$JAVA_HOME/bin/java"
150 | fi
151 | else
152 | JAVACMD="`\\unset -f command; \\command -v java`"
153 | fi
154 | fi
155 |
156 | if [ ! -x "$JAVACMD" ] ; then
157 | echo "Error: JAVA_HOME is not defined correctly." >&2
158 | echo " We cannot execute $JAVACMD" >&2
159 | exit 1
160 | fi
161 |
162 | if [ -z "$JAVA_HOME" ] ; then
163 | echo "Warning: JAVA_HOME environment variable is not set."
164 | fi
165 |
166 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
167 |
168 | # traverses directory structure from process work directory to filesystem root
169 | # first directory with .mvn subdirectory is considered project base directory
170 | find_maven_basedir() {
171 |
172 | if [ -z "$1" ]
173 | then
174 | echo "Path not specified to find_maven_basedir"
175 | return 1
176 | fi
177 |
178 | basedir="$1"
179 | wdir="$1"
180 | while [ "$wdir" != '/' ] ; do
181 | if [ -d "$wdir"/.mvn ] ; then
182 | basedir=$wdir
183 | break
184 | fi
185 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
186 | if [ -d "${wdir}" ]; then
187 | wdir=`cd "$wdir/.."; pwd`
188 | fi
189 | # end of workaround
190 | done
191 | echo "${basedir}"
192 | }
193 |
194 | # concatenates all lines of a file
195 | concat_lines() {
196 | if [ -f "$1" ]; then
197 | echo "$(tr -s '\n' ' ' < "$1")"
198 | fi
199 | }
200 |
201 | BASE_DIR=`find_maven_basedir "$(pwd)"`
202 | if [ -z "$BASE_DIR" ]; then
203 | exit 1;
204 | fi
205 |
206 | ##########################################################################################
207 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
208 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
209 | ##########################################################################################
210 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
211 | if [ "$MVNW_VERBOSE" = true ]; then
212 | echo "Found .mvn/wrapper/maven-wrapper.jar"
213 | fi
214 | else
215 | if [ "$MVNW_VERBOSE" = true ]; then
216 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
217 | fi
218 | if [ -n "$MVNW_REPOURL" ]; then
219 | jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
220 | else
221 | jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
222 | fi
223 | while IFS="=" read key value; do
224 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
225 | esac
226 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
227 | if [ "$MVNW_VERBOSE" = true ]; then
228 | echo "Downloading from: $jarUrl"
229 | fi
230 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
231 | if $cygwin; then
232 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
233 | fi
234 |
235 | if command -v wget > /dev/null; then
236 | if [ "$MVNW_VERBOSE" = true ]; then
237 | echo "Found wget ... using wget"
238 | fi
239 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
240 | wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
241 | else
242 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
243 | fi
244 | elif command -v curl > /dev/null; then
245 | if [ "$MVNW_VERBOSE" = true ]; then
246 | echo "Found curl ... using curl"
247 | fi
248 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
249 | curl -o "$wrapperJarPath" "$jarUrl" -f
250 | else
251 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
252 | fi
253 |
254 | else
255 | if [ "$MVNW_VERBOSE" = true ]; then
256 | echo "Falling back to using Java to download"
257 | fi
258 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
259 | # For Cygwin, switch paths to Windows format before running javac
260 | if $cygwin; then
261 | javaClass=`cygpath --path --windows "$javaClass"`
262 | fi
263 | if [ -e "$javaClass" ]; then
264 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
265 | if [ "$MVNW_VERBOSE" = true ]; then
266 | echo " - Compiling MavenWrapperDownloader.java ..."
267 | fi
268 | # Compiling the Java class
269 | ("$JAVA_HOME/bin/javac" "$javaClass")
270 | fi
271 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
272 | # Running the downloader
273 | if [ "$MVNW_VERBOSE" = true ]; then
274 | echo " - Running MavenWrapperDownloader.java ..."
275 | fi
276 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
277 | fi
278 | fi
279 | fi
280 | fi
281 | ##########################################################################################
282 | # End of extension
283 | ##########################################################################################
284 |
285 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
286 | if [ "$MVNW_VERBOSE" = true ]; then
287 | echo $MAVEN_PROJECTBASEDIR
288 | fi
289 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
290 |
291 | # For Cygwin, switch paths to Windows format before running java
292 | if $cygwin; then
293 | [ -n "$M2_HOME" ] &&
294 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
295 | [ -n "$JAVA_HOME" ] &&
296 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
297 | [ -n "$CLASSPATH" ] &&
298 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
299 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
300 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
301 | fi
302 |
303 | # Provide a "standardized" way to retrieve the CLI args that will
304 | # work with both Windows and non-Windows executions.
305 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
306 | export MAVEN_CMD_LINE_ARGS
307 |
308 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
309 |
310 | exec "$JAVACMD" \
311 | $MAVEN_OPTS \
312 | $MAVEN_DEBUG_OPTS \
313 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
314 | "-Dmaven.home=${M2_HOME}" \
315 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
316 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
317 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
124 |
125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% ^
162 | %JVM_CONFIG_MAVEN_PROPS% ^
163 | %MAVEN_OPTS% ^
164 | %MAVEN_DEBUG_OPTS% ^
165 | -classpath %WRAPPER_JAR% ^
166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
168 | if ERRORLEVEL 1 goto error
169 | goto end
170 |
171 | :error
172 | set ERROR_CODE=1
173 |
174 | :end
175 | @endlocal & set ERROR_CODE=%ERROR_CODE%
176 |
177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
181 | :skipRcPost
182 |
183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause
185 |
186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
187 |
188 | cmd /C exit /B %ERROR_CODE%
189 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | com.toomuchcoding.jsonassert
6 | jsonassert-parent
7 | pom
8 | 0.8.1-SNAPSHOT
9 |
10 | Json Assert Parent
11 | Json Assert Parent
12 | https://github.com/marcingrzejszczak/jsonassert
13 | 2015
14 |
15 |
16 |
17 | Apache License, Version 2.0
18 | https://www.apache.org/licenses/LICENSE-2.0
19 |
20 | Copyright 2014-2023 the original author or authors.
21 |
22 | Licensed under the Apache License, Version 2.0 (the "License");
23 | you may not use this file except in compliance with the License.
24 | You may obtain a copy of the License at
25 |
26 | https://www.apache.org/licenses/LICENSE-2.0
27 |
28 | Unless required by applicable law or agreed to in writing, software
29 | distributed under the License is distributed on an "AS IS" BASIS,
30 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
31 | implied.
32 |
33 | See the License for the specific language governing permissions and
34 | limitations under the License.
35 |
36 |
37 |
38 |
39 | https://github.com/marcingrzejszczak/jsonassert
40 | scm:git:git://github.com/marcingrzejszczak/jsonassert.git
41 |
42 |
43 | scm:git:ssh://git@github.com/marcingrzejszczak/jsonassert.git
44 |
45 | HEAD
46 |
47 |
48 |
49 | mgrzejszczak
50 | Marcin Grzejszczak
51 | marcin at grzejszczak.pl
52 |
53 | lead
54 |
55 |
56 |
57 |
58 | https://github.com/marcingrzejszczak/jsonassert
59 |
60 | jsonassert-docs
61 |
62 | https://github.com/marcingrzejszczak/jsonassert
63 |
64 |
65 |
66 | Nexus Release Repository
67 | sonatype-nexus-staging
68 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
69 |
70 |
71 |
72 |
73 | jsonassert
74 | jsonassert-assertj-java8
75 | jsonassert-shade
76 | tests
77 |
78 |
79 |
80 | 1.8
81 | UTF-8
82 | UTF-8
83 | ${java.version}
84 | ${java.version}
85 |
86 | 2.9.0
87 | 4.0.21
88 | 2.3-groovy-4.0
89 | 3.3.0
90 | 3.4
91 | 1.5.6
92 | 2.5.1
93 | 1.7.36
94 |
95 | 1.13.1
96 | 3.3.0
97 | 3.7.0
98 | 3.3.1
99 | 1.6
100 |
101 |
102 |
103 |
104 |
105 | com.jayway.jsonpath
106 | json-path
107 | ${json-path.version}
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | maven-javadoc-plugin
117 | ${maven-javadoc-plugin.version}
118 |
119 |
120 | javadoc
121 |
122 | jar
123 |
124 | package
125 |
126 |
127 |
128 |
129 | maven-source-plugin
130 | ${maven-source-plugin.version}
131 |
132 |
133 | attach-sources
134 |
135 | jar-no-fork
136 |
137 | prepare-package
138 |
139 |
140 |
141 |
142 | org.apache.maven.plugins
143 | maven-surefire-plugin
144 | ${maven-surefire-plugin.version}
145 |
146 |
147 | **/*Spec.*
148 | **/*Tests.*
149 | **/*Test.*
150 |
151 | plain
152 | true
153 |
154 |
155 |
156 | org.codehaus.gmavenplus
157 | gmavenplus-plugin
158 | ${gmavenplus-plugin.version}
159 |
160 |
161 |
162 | addTestSources
163 | compileTests
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 | org.apache.maven.plugins
174 | maven-release-plugin
175 | 3.1.0
176 |
177 | v@{project.version}
178 | central
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 | central
187 |
188 |
189 |
190 | org.apache.maven.plugins
191 | maven-gpg-plugin
192 | ${maven-gpg-plugin.version}
193 |
194 |
195 | sign-artifacts
196 | verify
197 |
198 | sign
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
--------------------------------------------------------------------------------
/release.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o errexit
4 |
5 | export DEV_VERSION="${DEV_VERSION:?You must set the next dev version}"
6 | export RELEASE_VERSION="${RELEASE_VERSION:?You must set the next release version}"
7 |
8 | echo "[RELEASE] Will release [${RELEASE_VERSION}] and then bump to dev version [${DEV_VERSION}]"
9 |
10 | echo "[RELEASE] Fetching tags..."
11 | git fetch --tags
12 |
13 | echo "[RELEASE] Preparing for the release..."
14 | ./mvnw -B -Dtag=v"${RELEASE_VERSION}" release:clean release:prepare -DreleaseVersion="${RELEASE_VERSION}" -DdevelopmentVersion="${DEV_VERSION}"
15 |
16 | echo "[RELEASE] Doing the actual release..."
17 | ./mvnw -B -Dtag=v"${RELEASE_VERSION}" -DreleaseVersion="${RELEASE_VERSION}" -DdevelopmentVersion="${DEV_VERSION}" -Dgoals=deploy release:perform -Pcentral
18 |
19 | echo "[RELEASE] Pushing tags..."
20 | git push origin main --tags
--------------------------------------------------------------------------------
/tests/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | jsonassert-tests
5 | 0.8.1-SNAPSHOT
6 |
7 |
8 | com.toomuchcoding.jsonassert
9 | jsonassert-parent
10 | 0.8.1-SNAPSHOT
11 | ..
12 |
13 |
14 |
15 |
16 | ${project.groupId}
17 | jsonassert-shade
18 | ${project.version}
19 | test
20 |
21 |
22 | org.apache.groovy
23 | groovy-json
24 | ${groovy.version}
25 | test
26 |
27 |
28 | org.spockframework
29 | spock-core
30 | ${spock.version}
31 | test
32 |
33 |
34 | cglib
35 | cglib-nodep
36 | ${cglib-nodep.version}
37 | test
38 |
39 |
40 | org.objenesis
41 | objenesis
42 | ${objenesis.version}
43 | test
44 |
45 |
46 | ch.qos.logback
47 | logback-classic
48 | ${logback-classic.version}
49 | test
50 |
51 |
52 |
53 |
54 |
55 |
56 | org.codehaus.gmavenplus
57 | gmavenplus-plugin
58 |
59 |
60 | org.apache.maven.plugins
61 | maven-surefire-plugin
62 |
63 | false
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/tests/src/test/groovy/shaded/com/toomuchcoding/jsonassert/JsonAssertionSpec.groovy:
--------------------------------------------------------------------------------
1 | package shaded.com.toomuchcoding.jsonassert
2 |
3 | import shaded.com.jayway.jsonpath.DocumentContext
4 | import shaded.com.jayway.jsonpath.JsonPath
5 | import shaded.com.jayway.jsonpath.PathNotFoundException
6 | import shaded.net.minidev.json.JSONArray
7 | import spock.lang.Issue
8 | import spock.lang.Shared
9 | import spock.lang.Specification
10 | import spock.lang.Unroll
11 |
12 | import static com.toomuchcoding.jsonassert.JsonAssertion.assertThat
13 | import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson
14 | import static groovy.json.JsonOutput.toJson
15 |
16 | /**
17 | * @author Marcin Grzejszczak
18 | */
19 | class JsonAssertionSpec extends Specification {
20 |
21 | @Shared String json1 = '''
22 | {
23 | "some" : {
24 | "nested" : {
25 | "json" : "with \\"val'ue",
26 | "anothervalue": 4,
27 | "withlist" : [
28 | { "name" :"name1"} , {"name": "name2"}
29 | ]
30 | }
31 | }
32 | }
33 | '''
34 |
35 | @Unroll
36 | def 'should convert a json with a map as root to a map of path to value '() {
37 | expect:
38 | verifiable.jsonPath() == expectedJsonPath
39 | and:
40 | JsonPath.parse(json1).read(expectedJsonPath, JSONArray)
41 | where:
42 | verifiable || expectedJsonPath
43 | assertThat(json1).field("some").field("nested").field("anothervalue").isEqualTo(4) || '''$.some.nested[?(@.anothervalue == 4)]'''
44 | assertThat(json1).field("some").field("nested").field("anothervalue") || '''$.some.nested.anothervalue'''
45 | assertThatJson(json1).field("some").field("nested").field("anothervalue").isEqualTo(4) || '''$.some.nested[?(@.anothervalue == 4)]'''
46 | assertThat(json1).field("some").field("nested").array("withlist").contains("name").isEqualTo("name1") || '''$.some.nested.withlist[*][?(@.name == 'name1')]'''
47 | assertThat(json1).field("some").field("nested").array("withlist").contains("name").isEqualTo("name2") || '''$.some.nested.withlist[*][?(@.name == 'name2')]'''
48 | assertThat(json1).field("some").field("nested").field("json").isEqualTo("with \"val'ue") || '''$.some.nested[?(@.json == 'with "val\\'ue')]'''
49 | assertThat(json1).field("some", "nested", "json").isEqualTo("with \"val'ue") || '''$.some.nested[?(@.json == 'with "val\\'ue')]'''
50 | }
51 |
52 | @Shared String json2 = '''{
53 | "property1": "a",
54 | "property2": "b"
55 | }'''
56 |
57 | @Unroll
58 | def "should generate assertions for simple response body"() {
59 | expect:
60 | verifiable.jsonPath() == expectedJsonPath
61 | and:
62 | JsonPath.parse(json2).read(expectedJsonPath, JSONArray)
63 | where:
64 | verifiable || expectedJsonPath
65 | assertThat(json2).field("property1").isEqualTo("a") || '''$[?(@.property1 == 'a')]'''
66 | assertThat(json2).field("property2").isEqualTo("b") || '''$[?(@.property2 == 'b')]'''
67 | }
68 |
69 | @Shared String json3 = '''{
70 | "property1": "true",
71 | "property2": null,
72 | "property3": false
73 | }'''
74 |
75 | @Unroll
76 | def "should generate assertions for null and boolean values"() {
77 | expect:
78 | verifiable.jsonPath() == expectedJsonPath
79 | and:
80 | JsonPath.parse(json3).read(expectedJsonPath, JSONArray)
81 | where:
82 | verifiable || expectedJsonPath
83 | assertThat(json3).field("property1").isEqualTo("true") || '''$[?(@.property1 == 'true')]'''
84 | assertThat(json3).field("property2").isNull() || '''$[?(@.property2 == null)]'''
85 | assertThat(json3).field("property3").isEqualTo(false) || '''$[?(@.property3 == false)]'''
86 | }
87 |
88 | @Shared Map json4 = [
89 | property1: 'a',
90 | property2: [
91 | [a: 'sth'],
92 | [b: 'sthElse']
93 | ]
94 | ]
95 |
96 | @Unroll
97 | def "should generate assertions for simple response body constructed from map with a list"() {
98 | expect:
99 | verifiable.jsonPath() == expectedJsonPath
100 | and:
101 | JsonPath.parse(json4).read(expectedJsonPath, JSONArray)
102 | where:
103 | verifiable || expectedJsonPath
104 | assertThat(toJson(json4)).field("property1").isEqualTo("a") || '''$[?(@.property1 == 'a')]'''
105 | assertThat(toJson(json4)).array("property2").contains("a").isEqualTo("sth") || '''$.property2[*][?(@.a == 'sth')]'''
106 | assertThat(toJson(json4)).array("property2").contains("b").isEqualTo("sthElse") || '''$.property2[*][?(@.b == 'sthElse')]'''
107 | }
108 |
109 | @Shared Map json5 = [
110 | property: [
111 | 14: 0.0,
112 | 7 : 0.0
113 | ]
114 | ]
115 |
116 | @Unroll
117 | def "should generate assertions for a response body containing map with integers as keys"() {
118 | expect:
119 | verifiable.jsonPath() == expectedJsonPath
120 | and:
121 | JsonPath.parse(toJson(json5)).read(expectedJsonPath, JSONArray)
122 | where:
123 | verifiable || expectedJsonPath
124 | assertThat(toJson(json5)).field("property").field(7).isEqualTo(0.0) || '''$.property[?(@.7 == 0.0)]'''
125 | assertThat(toJson(json5)).field("property").field(14).isEqualTo(0.0) || '''$.property[?(@.14 == 0.0)]'''
126 | }
127 |
128 | @Shared String json6 = '''[
129 | {
130 | "property1": "a"
131 | },
132 | {
133 | "property2": "b"
134 | }]'''
135 |
136 | @Unroll
137 | def "should generate assertions for array in response body"() {
138 | expect:
139 | verifiable.jsonPath() == expectedJsonPath
140 | and:
141 | JsonPath.parse(json6).read(expectedJsonPath, JSONArray)
142 | where:
143 | verifiable || expectedJsonPath
144 | assertThat(json6).array().contains("property1").isEqualTo("a") || '''$[*][?(@.property1 == 'a')]'''
145 | assertThat(json6).array().contains("property2").isEqualTo("b") || '''$[*][?(@.property2 == 'b')]'''
146 | }
147 |
148 | @Shared String json7 = '''{
149 | "property1": [
150 | { "property2": "test1"},
151 | { "property3": "test2"}
152 | ]
153 | }'''
154 |
155 | @Unroll
156 | def "should generate assertions for array inside response body element"() {
157 | expect:
158 | verifiable.jsonPath() == expectedJsonPath
159 | and:
160 | JsonPath.parse(json7).read(expectedJsonPath, JSONArray)
161 | where:
162 | verifiable || expectedJsonPath
163 | assertThat(json7).array("property1").contains("property2").isEqualTo("test1") || '''$.property1[*][?(@.property2 == 'test1')]'''
164 | assertThat(json7).array("property1").contains("property3").isEqualTo("test2") || '''$.property1[*][?(@.property3 == 'test2')]'''
165 | }
166 |
167 | @Shared String json8 = """{
168 | "property1": "a",
169 | "property2": {"property3": "b"}
170 | }"""
171 |
172 | def "should generate assertions for nested objects in response body"() {
173 | expect:
174 | verifiable.jsonPath() == expectedJsonPath
175 | and:
176 | JsonPath.parse(json8).read(expectedJsonPath, JSONArray)
177 | where:
178 | verifiable || expectedJsonPath
179 | assertThat(json8).field("property2").field("property3").isEqualTo("b") || '''$.property2[?(@.property3 == 'b')]'''
180 | assertThat(json8).field("property1").isEqualTo("a") || '''$[?(@.property1 == 'a')]'''
181 | }
182 |
183 | @Shared Map json9 = [
184 | property1: "a",
185 | property2: 123
186 | ]
187 |
188 | @Unroll
189 | def "should generate regex assertions for map objects in response body"() {
190 | expect:
191 | verifiable.jsonPath() == expectedJsonPath
192 | and:
193 | JsonPath.parse(json9).read(expectedJsonPath, JSONArray)
194 | where:
195 | verifiable || expectedJsonPath
196 | assertThat(toJson(json9)).field("property2").matches("[0-9]{3}") || '''$[?(@.property2 =~ /[0-9]{3}/)]'''
197 | assertThat(toJson(json9)).field("property1").isEqualTo("a") || '''$[?(@.property1 == 'a')]'''
198 | }
199 |
200 | def "should generate escaped regex assertions for string objects in response body"() {
201 | given:
202 | Map json = [
203 | property2: 123123
204 | ]
205 | expect:
206 | def verifiable = assertThat(toJson(json)).field("property2").matches("\\d+")
207 | verifiable.jsonPath() == '''$[?(@.property2 =~ /\\d+/)]'''
208 | and:
209 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
210 | }
211 |
212 | @Shared Map json10 = [
213 | errors: [
214 | [property: "bank_account_number",
215 | message: "incorrect_format"]
216 | ]
217 | ]
218 |
219 | @Unroll
220 | def "should work with more complex stuff and jsonpaths"() {
221 | expect:
222 | verifiable.jsonPath() == expectedJsonPath
223 | and:
224 | JsonPath.parse(json10).read(expectedJsonPath, JSONArray)
225 | where:
226 | verifiable || expectedJsonPath
227 | assertThat(toJson(json10)).array("errors").contains("property").isEqualTo("bank_account_number") || '''$.errors[*][?(@.property == 'bank_account_number')]'''
228 | assertThat(toJson(json10)).array("errors").contains("message").isEqualTo("incorrect_format") || '''$.errors[*][?(@.message == 'incorrect_format')]'''
229 | }
230 |
231 | @Shared String json11 = '''
232 | [{
233 | "place":
234 | {
235 | "bounding_box":
236 | {
237 | "coordinates":
238 | [[
239 | [-77.119759,38.995548],
240 | [-76.909393,38.791645]
241 | ]]
242 | }
243 | }
244 | }]
245 | '''
246 |
247 | @Unroll
248 | def "should manage to parse a triple array"() {
249 | expect:
250 | verifiable.jsonPath() == expectedJsonPath
251 | and:
252 | JsonPath.parse(json11).read(expectedJsonPath, JSONArray)
253 | where:
254 | verifiable || expectedJsonPath
255 | assertThat(json11).array().field("place").field("bounding_box").array("coordinates").array().array().arrayField().contains(38.995548).value() || '''$[*].place.bounding_box.coordinates[*][*][?(@ == 38.995548)]'''
256 | assertThat(json11).array().field("place").field("bounding_box").array("coordinates").array().array().arrayField().contains(-77.119759).value() || '''$[*].place.bounding_box.coordinates[*][*][?(@ == -77.119759)]'''
257 | assertThat(json11).array().field("place").field("bounding_box").array("coordinates").array().array().arrayField().contains(-76.909393).value() || '''$[*].place.bounding_box.coordinates[*][*][?(@ == -76.909393)]'''
258 | assertThat(json11).array().field("place").field("bounding_box").array("coordinates").array().array().arrayField().contains(38.791645).value() || '''$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]'''
259 |
260 | }
261 |
262 | @Shared String json12 = '''
263 | [{
264 | "place":
265 | {
266 | "bounding_box":
267 | {
268 | "coordinates":
269 | [[[
270 | [-77.119759,38.995548],
271 | [-76.909393,38.791645]
272 | ]]]
273 | }
274 | }
275 | }]
276 | '''
277 |
278 | @Unroll
279 | def "should manage to parse a quadriple array"() {
280 | expect:
281 | verifiable.jsonPath() == expectedJsonPath
282 | and:
283 | JsonPath.parse(json12).read(expectedJsonPath, JSONArray)
284 | where:
285 | verifiable || expectedJsonPath
286 | assertThat(json12).array().field("place").field("bounding_box").array("coordinates").array().array().array().arrayField().contains(38.995548).value() || '''$[*].place.bounding_box.coordinates[*][*][*][?(@ == 38.995548)]'''
287 | assertThat(json12).array().field("place").field("bounding_box").array("coordinates").array().array().array().arrayField().contains(-77.119759).value() || '''$[*].place.bounding_box.coordinates[*][*][*][?(@ == -77.119759)]'''
288 | assertThat(json12).array().field("place").field("bounding_box").array("coordinates").array().array().array().arrayField().contains(-76.909393).value() || '''$[*].place.bounding_box.coordinates[*][*][*][?(@ == -76.909393)]'''
289 | assertThat(json12).array().field("place").field("bounding_box").array("coordinates").array().array().array().arrayField().contains(38.791645).value() || '''$[*].place.bounding_box.coordinates[*][*][*][?(@ == 38.791645)]'''
290 |
291 | }
292 |
293 | @Shared String jsonArrayInArray= '''
294 | {
295 | "coordinates":
296 | [
297 | [-77.119759,38.995548],
298 | [-76.909393,38.791645]
299 | ]
300 | }
301 | }
302 | '''
303 |
304 | @Unroll
305 | def "should manage to parse array in array"() {
306 | expect:
307 | verifiable.jsonPath() == expectedJsonPath
308 | and:
309 | JsonPath.parse(jsonArrayInArray).read(expectedJsonPath, JSONArray)
310 | where:
311 | verifiable || expectedJsonPath
312 | assertThat(jsonArrayInArray).array("coordinates").array().arrayField().contains(38.995548).value() || '''$.coordinates[*][?(@ == 38.995548)]'''
313 | assertThat(jsonArrayInArray).array("coordinates").array().arrayField().contains(-77.119759).value() || '''$.coordinates[*][?(@ == -77.119759)]'''
314 | assertThat(jsonArrayInArray).array("coordinates").array().arrayField().contains(-76.909393).value() || '''$.coordinates[*][?(@ == -76.909393)]'''
315 | assertThat(jsonArrayInArray).array("coordinates").array().arrayField().contains(38.791645).value() || '''$.coordinates[*][?(@ == 38.791645)]'''
316 | }
317 |
318 | @Unroll
319 | def 'should convert a json with list as root to a map of path to value'() {
320 | expect:
321 | assertThat(json).array().field("some").field("nested").field("json").isEqualTo("with value").jsonPath() == '''$[*].some.nested[?(@.json == 'with value')]'''
322 | assertThat(json).array().field("some").field("nested").field("anothervalue").isEqualTo(4).jsonPath() == '''$[*].some.nested[?(@.anothervalue == 4)]'''
323 | assertThat(json).array().field("some").field("nested").array("withlist").contains("name").isEqualTo("name1").jsonPath() == '''$[*].some.nested.withlist[*][?(@.name == 'name1')]'''
324 | assertThat(json).array().field("some").field("nested").array("withlist").contains("name").isEqualTo("name2").jsonPath() == '''$[*].some.nested.withlist[*][?(@.name == 'name2')]'''
325 | assertThat(json).array().field("some").field("nested").array("withlist").field("anothernested").field("name").isEqualTo("name3").jsonPath() == '''$[*].some.nested.withlist[*].anothernested[?(@.name == 'name3')]'''
326 | where:
327 | json << [
328 | '''
329 | [ {
330 | "some" : {
331 | "nested" : {
332 | "json" : "with value",
333 | "anothervalue": 4,
334 | "withlist" : [
335 | { "name" :"name1"} , {"name": "name2"}, {"anothernested": { "name": "name3"} }
336 | ]
337 | }
338 | }
339 | },
340 | {
341 | "someother" : {
342 | "nested" : {
343 | "json" : "with value",
344 | "anothervalue": 4,
345 | "withlist" : [
346 | { "name" :"name1"} , {"name": "name2"}
347 | ]
348 | }
349 | }
350 | }
351 | ]
352 | ''',
353 | '''
354 | [{
355 | "someother" : {
356 | "nested" : {
357 | "json" : "with value",
358 | "anothervalue": 4,
359 | "withlist" : [
360 | { "name" :"name1"} , {"name": "name2"}
361 | ]
362 | }
363 | }
364 | },
365 | {
366 | "some" : {
367 | "nested" : {
368 | "json" : "with value",
369 | "anothervalue": 4,
370 | "withlist" : [
371 | {"name": "name2"}, {"anothernested": { "name": "name3"} }, { "name" :"name1"}
372 | ]
373 | }
374 | }
375 | }
376 | ]''']
377 | }
378 |
379 | def "should run json path when provided manually"() {
380 | given:
381 | String json = """{
382 | "property1": "a",
383 | "property2": {"property3": "b"}
384 | }"""
385 | and:
386 | String jsonPath = '''$[?(@.property1 == 'a')]'''
387 | expect:
388 | assertThat(json).matchesJsonPath(jsonPath)
389 | and:
390 | JsonPath.parse(json).read(jsonPath, JSONArray)
391 | }
392 |
393 | def "should throw exception when json path is not matched"() {
394 | given:
395 | String json = """{
396 | "property1": "a",
397 | "property2": {"property3": "b"}
398 | }"""
399 | and:
400 | String jsonPath = '''$[?(@.property1 == 'c')]'''
401 | when:
402 | assertThat(json).matchesJsonPath(jsonPath)
403 | then:
404 | IllegalStateException illegalStateException = thrown(IllegalStateException)
405 | illegalStateException.message.contains("Parsed JSON")
406 | illegalStateException.message.contains("doesn't match")
407 | }
408 |
409 | def "should not throw exception when json path is not matched and system prop overrides the check"() {
410 | given:
411 | String json = """{
412 | "property1": "a",
413 | "property2": {"property3": "b"}
414 | }"""
415 | and:
416 | String jsonPath = '''$[?(@.property1 == 'c')]'''
417 | when:
418 | assertThat(json).withoutThrowingException().matchesJsonPath(jsonPath)
419 | then:
420 | noExceptionThrown()
421 | }
422 |
423 | def "should generate escaped regex assertions for boolean objects in response body"() {
424 | given:
425 | Map json = [
426 | property2: true
427 | ]
428 | expect:
429 | def verifiable = assertThat(toJson(json)).field("property2").matches('true|false')
430 | verifiable.jsonPath() == '''$[?(@.property2 =~ /true|false/)]'''
431 | and:
432 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
433 | }
434 |
435 | def "should generate escaped regex assertions for numbers objects in response body"() {
436 | given:
437 | Map json = [
438 | property2: 50
439 | ]
440 | expect:
441 | def verifiable = assertThat(toJson(json)).field("property2").matches('[0-9]{2}')
442 | verifiable.jsonPath() == '''$[?(@.property2 =~ /[0-9]{2}/)]'''
443 | and:
444 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
445 | }
446 |
447 | def "should escape regular expression properly"() {
448 | given:
449 | String json = """
450 | {
451 | "path" : "/api/12",
452 | "correlationId" : 123456
453 | }
454 | """
455 | expect:
456 | DocumentContext parsedJson = JsonPath.parse(json)
457 | def verifiable = assertThatJson(parsedJson).field("path").matches("^/api/[0-9]{2}\$")
458 | verifiable.jsonPath() == '''$[?(@.path =~ /^\\/api\\/[0-9]{2}$/)]'''
459 | and:
460 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
461 | }
462 |
463 | @Issue("Accurest#193")
464 | def "should escape single quotes in a quoted string"() {
465 | given:
466 | String json = """
467 | {
468 | "text" : "text with 'quotes' inside"
469 | }
470 | """
471 | expect:
472 | DocumentContext parsedJson = JsonPath.parse(json)
473 | def verifiable = assertThatJson(parsedJson).field("text").isEqualTo("text with 'quotes' inside")
474 | verifiable.jsonPath() == '''$[?(@.text == 'text with \\'quotes\\' inside')]'''
475 | and:
476 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
477 | }
478 |
479 | @Issue("Accurest#193")
480 | def "should escape double quotes in a quoted string"() {
481 | given:
482 | String json = """
483 | {
484 | "text" : "text with \\"quotes\\" inside"
485 | }
486 | """
487 | expect:
488 | DocumentContext parsedJson = JsonPath.parse(json)
489 | def verifiable = assertThatJson(parsedJson).field("text").isEqualTo('''text with "quotes" inside''')
490 | verifiable.jsonPath() == '''$[?(@.text == 'text with "quotes" inside')]'''
491 | and:
492 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
493 | }
494 |
495 | def 'should resolve the value of JSON via JSON Path'() {
496 | given:
497 | String json =
498 | '''
499 | [ {
500 | "some" : {
501 | "nested" : {
502 | "json" : "with value",
503 | "anothervalue": 4,
504 | "withlist" : [
505 | { "name" :"name1"} ,
506 | {"name": "name2"},
507 | {"anothernested": { "name": "name3"} }
508 | ]
509 | }
510 | }
511 | },
512 | {
513 | "someother" : {
514 | "nested" : {
515 | "json" : true,
516 | "anothervalue": 4,
517 | "withlist" : [
518 | { "name" :"name1"} , {"name": "name2"}
519 | ],
520 | "withlist2" : [
521 | "a", "b"
522 | ]
523 | }
524 | }
525 | }
526 | ]
527 | '''
528 | expect:
529 | com.toomuchcoding.jsonassert.JsonPath.builder(json).array().field("some").field("nested").field("json").read(String) == 'with value'
530 | com.toomuchcoding.jsonassert.JsonPath.builder(json).array().field("some").field("nested").field("anothervalue").read(Integer) == 4
531 | assertThat(json).array().field("some").field("nested").array("withlist").field("name").read(List) == ['name1', 'name2']
532 | assertThat(json).array().field("someother").field("nested").array("withlist2").read(List) == ['a', 'b']
533 | assertThat(json).array().field("someother").field("nested").field("json").read(Boolean) == true
534 | }
535 |
536 | def 'should assert json with only top list elements'() {
537 | given:
538 | String json = '''["Java", "Java8", "Spring", "SpringBoot", "Stream"]'''
539 | expect:
540 | assertThatJson(json).arrayField().contains("Java8").value()
541 | assertThatJson(json).arrayField().contains("Spring").value()
542 | assertThatJson(json).arrayField().contains("Java").value()
543 | assertThatJson(json).arrayField().contains("Stream").value()
544 | assertThatJson(json).arrayField().contains("SpringBoot").value()
545 | }
546 |
547 | @Issue("#9")
548 | def 'should match array containing an array of primitives'() {
549 | given:
550 | String json = '''{"first_name":"existing",
551 | "partners":[
552 | { "role":"AGENT",
553 | "payment_methods":[ "BANK", "CASH" ]
554 | }
555 | ]
556 | }'''
557 | expect:
558 | def verifiable = assertThatJson(json).array("partners").array("payment_methods").arrayField().isEqualTo("BANK").value()
559 | verifiable.jsonPath() == '''$.partners[*].payment_methods[?(@ == 'BANK')]'''
560 | and:
561 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
562 | }
563 |
564 | @Issue("#9")
565 | def 'should match pattern in array'() {
566 | given:
567 | String json = '''{ "authorities": ["ROLE_ADMIN"] }'''
568 | expect:
569 | def verifiable = assertThatJson(json).array("authorities").arrayField().matches("^[a-zA-Z0-9_\\- ]+\$").value()
570 | verifiable.jsonPath() == '''$.authorities[?(@ =~ /^[a-zA-Z0-9_\\- ]+$/)]'''
571 | and:
572 | JsonPath.parse(json).read(verifiable.jsonPath(), JSONArray)
573 | }
574 |
575 | @Issue("#10")
576 | def 'should manage to parse array with string values'() {
577 | given:
578 | String json = '''{ "some_list" : ["name1", "name2"] }'''
579 | expect:
580 | def v1 = assertThat(JsonPath.parse(json)).array("some_list").arrayField().isEqualTo("name1")
581 | def v2 = assertThat(JsonPath.parse(json)).array("some_list").arrayField().isEqualTo("name2")
582 | and:
583 | v1.jsonPath() == '''$.some_list[?(@ == 'name1')]'''
584 | v2.jsonPath() == '''$.some_list[?(@ == 'name2')]'''
585 | and:
586 | JsonPath.parse(json).read(v1.jsonPath(), JSONArray)
587 | JsonPath.parse(json).read(v2.jsonPath(), JSONArray)
588 | }
589 |
590 | def 'should parse an array of arrays that are root elements'() {
591 | given:
592 | String json = '''[["Programming", "Java"], ["Programming", "Java", "Spring", "Boot"]]'''
593 | expect:
594 | def v1 = assertThatJson(JsonPath.parse(json)).array().arrayField().isEqualTo("Java").value()
595 | and:
596 | v1.jsonPath() == '''$[*][?(@ == 'Java')]'''
597 | and:
598 | JsonPath.parse(json).read(v1.jsonPath(), JSONArray)
599 | }
600 |
601 | @Issue('#11')
602 | def 'should allow to check array size'() {
603 | given:
604 | String json = '''{ "some_list" : ["name1", "name2"] }'''
605 | expect:
606 | assertThat(json).array("some_list").hasSize(2)
607 | when:
608 | assertThat(json).array("some_list").hasSize(5)
609 | then:
610 | def ex = thrown(RuntimeException)
611 | ex instanceof IllegalStateException
612 | ex.message == '''Parsed JSON <{"some_list":["name1","name2"]}> doesn't have the size <5> for JSON path <$.some_list[*]>. The size is <2>'''
613 | }
614 |
615 | @Issue('#11')
616 | def 'should allow to check size of root array'() {
617 | given:
618 | String json = '''["name1", "name2"]'''
619 | expect:
620 | assertThat(json).hasSize(2)
621 | when:
622 | assertThat(json).hasSize(5)
623 | then:
624 | def ex = thrown(RuntimeException)
625 | ex instanceof IllegalStateException
626 | ex.message == '''Parsed JSON <["name1","name2"]> doesn't have the size <5> for JSON path <$>. The size is <2>'''
627 | }
628 |
629 | @Issue('#11')
630 | def 'should allow to check size of a nested array'() {
631 | given:
632 | String json =
633 | '''
634 | [ {
635 | "some" : {
636 | "nested" : {
637 | "json" : "with value",
638 | "anothervalue": 4,
639 | "withlist" : [
640 | { "name" :"name1"} ,
641 | {"name": "name2"},
642 | {"anothernested": { "name": "name3"} }
643 | ]
644 | }
645 | }
646 | },
647 | {
648 | "someother" : {
649 | "nested" : {
650 | "json" : true,
651 | "anothervalue": 4,
652 | "withlist" : [
653 | { "name" :"name1"} , {"name": "name2"}
654 | ],
655 | "withlist2" : [
656 | "a", "b"
657 | ]
658 | }
659 | }
660 | }
661 | ]'''
662 | expect:
663 | assertThat(json).array().field("someother").field("nested").array("withlist2").hasSize(2)
664 | when:
665 | assertThat(json).array().field("someother").field("nested").array("withlist2").hasSize(5)
666 | then:
667 | def ex = thrown(RuntimeException)
668 | ex instanceof IllegalStateException
669 | ex.message == '''Parsed JSON <[{"some":{"nested":{"json":"with value","anothervalue":4,"withlist":[{"name":"name1"},{"name":"name2"},{"anothernested":{"name":"name3"}}]}}},{"someother":{"nested":{"json":true,"anothervalue":4,"withlist":[{"name":"name1"},{"name":"name2"}],"withlist2":["a","b"]}}}]> doesn't have the size <5> for JSON path <$[*].someother.nested.withlist2[*]>. The size is <2>'''
670 | }
671 |
672 | @Issue('#11')
673 | def 'should allow to check size of a named array'() {
674 | given:
675 | def json = [
676 | property1: 'a',
677 | property2: [
678 | [a: 'sth'],
679 | [b: 'sthElse']
680 | ]
681 | ]
682 | expect:
683 | assertThat(toJson(json)).array("property2").hasSize(2)
684 | when:
685 | assertThat(toJson(json)).array("property2").hasSize(5)
686 | then:
687 | def ex = thrown(RuntimeException)
688 | ex instanceof IllegalStateException
689 | ex.message == '''Parsed JSON <{"property1":"a","property2":[{"a":"sth"},{"b":"sthElse"}]}> doesn't have the size <5> for JSON path <$.property2[*]>. The size is <2>'''
690 | }
691 |
692 | @Issue('#11')
693 | def 'should allow to check size of two nameless arrays'() {
694 | given:
695 | String json = '''[["Programming", "Java"], ["Programming", "Java", "Spring", "Boot"], ["Programming", "Java", "Spring", "Boot", "Master"]]'''
696 | expect:
697 | assertThat(json).hasSize(3)
698 | assertThat(json).elementWithIndex(0).hasSize(2)
699 | assertThat(json).elementWithIndex(1).hasSize(4)
700 | when:
701 | assertThat(json).array().hasSize(4)
702 | then:
703 | def ex = thrown(RuntimeException)
704 | ex instanceof IllegalStateException
705 | ex.message == '''Parsed JSON <[["Programming","Java"],["Programming","Java","Spring","Boot"],["Programming","Java","Spring","Boot","Master"]]> doesn't have the size <4> for JSON path <$[*]>. The size is <3>'''
706 | }
707 |
708 | @Issue('#11')
709 | def 'should allow to check size of two nameless arrays in a nameless array'() {
710 | given:
711 | String json = '''[[["Programming", "Java"], ["Programming", "Java", "Spring", "Boot"]]]'''
712 | expect:
713 | assertThat(json).hasSize(1)
714 | assertThat(json).elementWithIndex(0).elementWithIndex(0).hasSize(2)
715 | assertThat(json).elementWithIndex(0).elementWithIndex(1).hasSize(4)
716 | when:
717 | assertThat(json).elementWithIndex(0).elementWithIndex(1).hasSize(5)
718 | then:
719 | def ex = thrown(RuntimeException)
720 | ex instanceof IllegalStateException
721 | ex.message == '''Parsed JSON <[[["Programming","Java"],["Programming","Java","Spring","Boot"]]]> doesn't have the size <5> for JSON path <$[0][1]>. The size is <4>'''
722 | }
723 |
724 | @Issue('#11')
725 | def 'should allow to check array size of nameless array'() {
726 | given:
727 | String json = '''{ "coordinates" : [[
728 | ["name1", "name2"],
729 | ["name3", "name4"]
730 | ]] }'''
731 | expect:
732 | assertThat(json).array("coordinates").array().hasSize(2)
733 | when:
734 | assertThat(json).array("coordinates").array().hasSize(5)
735 | then:
736 | def ex = thrown(RuntimeException)
737 | ex instanceof IllegalStateException
738 | ex.message == '''Parsed JSON <{"coordinates":[[["name1","name2"],["name3","name4"]]]}> doesn't have the size <5> for JSON path <$.coordinates[*][*]>. The size is <2>'''
739 | }
740 |
741 | @Unroll
742 | def 'should fail on non existent path'() {
743 | when:
744 | assertThat(json instanceof Map ? toJson(json) : json).field("non").field("existant").field("field").isEqualTo("imaginary value")
745 | then:
746 | def ex = thrown(RuntimeException)
747 | ex.cause instanceof PathNotFoundException
748 | where:
749 | json << [ json1, json2, json3, json4, json5, json6, json7, json8, json9, json10, json11 ]
750 | }
751 |
752 | @Issue('#14')
753 | def 'should allow to check if size is empty'() {
754 | given:
755 | String json = '''{ "coordinates" : [], "foo": ["bar", "baz"] }'''
756 | expect:
757 | assertThat(json).array("coordinates").isEmpty()
758 | when:
759 | assertThat(json).array("foo").isEmpty()
760 | then:
761 | def ex = thrown(RuntimeException)
762 | ex instanceof IllegalStateException
763 | ex.message == '''Parsed JSON [{"coordinates":[],"foo":["bar","baz"]}] with the JSON path [$.foo[*]] is not empty!'''
764 | }
765 |
766 | @Issue('#17')
767 | def 'should ignore exception on empty check'() {
768 | given:
769 | String json = '''{ "coordinates" : [], "foo": ["bar", "baz"] }'''
770 | when:
771 | assertThat(json).withoutThrowingException().array("foo").isEmpty()
772 | then:
773 | noExceptionThrown()
774 | }
775 |
776 | @Issue('#16')
777 | def 'should throw exception when an empty array is returned'() {
778 | given:
779 | String json = '''{}'''
780 | when:
781 | assertThatJson(json).field("doesNotExist").matches("[\\p{L}]*")
782 | then:
783 | def ex = thrown(RuntimeException)
784 | ex instanceof IllegalStateException
785 | ex.message == '''Parsed JSON [{}] doesn't match the JSON path [$[?(@.doesNotExist =~ /[\\p{L}]*/)]]'''
786 | when:
787 | assertThatJson(json).array("c").matches("[\\p{L}]*")
788 | then:
789 | ex = thrown(RuntimeException)
790 | ex instanceof IllegalStateException
791 | ex.message == '''Parsed JSON [{}] doesn't match the JSON path [$[?(@.c =~ /[\\p{L}]*/)]]'''
792 | }
793 |
794 | @Issue('#18')
795 | def 'should read types of objects'() {
796 | given:
797 | String json = '''{ "foo": 46 }'''
798 | when:
799 | assertThatJson(json).field("foo").isInstanceOf(Number)
800 | then:
801 | noExceptionThrown()
802 | when:
803 | assertThatJson(json).field("foo").isInstanceOf(String)
804 | then:
805 | RuntimeException ex = thrown(RuntimeException)
806 | ex instanceof IllegalStateException
807 | ex.message == '''For JSON path [$.foo] instance of [Integer] is not assignable from [String]'''
808 | }
809 |
810 | @Issue('#18')
811 | def 'should read big numbers'() {
812 | given:
813 | String json = '''{ "largeNum": 55534673.56, "bigInt": 2147483647, "decimals": 0.1287361923123}'''
814 | when:
815 | assertThatJson(json).field("largeNum").isEqualTo(55534673.56 as Double)
816 | then:
817 | noExceptionThrown()
818 | when:
819 | assertThatJson(json).field("bigInt").isEqualTo(Integer.MAX_VALUE as Integer)
820 | then:
821 | noExceptionThrown()
822 | when:
823 | assertThatJson(json).field("decimals").isEqualTo(0.1287361923123 as Double)
824 | then:
825 | noExceptionThrown()
826 | }
827 |
828 | @Issue('#28')
829 | def 'should match {} as empty'() {
830 | given:
831 | String json = '''{ "field1": {}, field2: [] }}'''
832 | when:
833 | assertThatJson(json).field("field1").isEmpty()
834 | then:
835 | noExceptionThrown()
836 | when:
837 | assertThatJson(json).field("field2").isEmpty()
838 | then:
839 | noExceptionThrown()
840 | }
841 |
842 | @Issue('#31')
843 | def 'should work with scientific notation'() {
844 | given:
845 | String json = '''{ "n": 1.12E-12}'''
846 | when:
847 | assertThatJson(json).field("n").isEqualTo(1.12E-12)
848 | then:
849 | noExceptionThrown()
850 | }
851 |
852 | }
853 |
--------------------------------------------------------------------------------
/tests/src/test/groovy/shaded/com/toomuchcoding/jsonassert/JsonPathSpec.groovy:
--------------------------------------------------------------------------------
1 | package shaded.com.toomuchcoding.jsonassert
2 |
3 | import com.toomuchcoding.jsonassert.JsonPath
4 | import spock.lang.Specification
5 |
6 | /**
7 | * @author Marcin Grzejszczak
8 | */
9 | class JsonPathSpec extends Specification {
10 |
11 | def "should generate proper JSON paths"() {
12 | expect:
13 | jsonPath == expectedJsonPath
14 | where:
15 | jsonPath || expectedJsonPath
16 | JsonPath.builder().field("some").field("nested").field("anothervalue").isEqualTo(4).jsonPath() || '''$.some.nested[?(@.anothervalue == 4)]'''
17 | JsonPath.builder().field("some").field("nested").field("anothervalue").isEqualTo(4).jsonPath() || '''$.some.nested[?(@.anothervalue == 4)]'''
18 | JsonPath.builder().field("some").field("nested").array("withlist").contains("name").isEqualTo("name1").jsonPath() || '''$.some.nested.withlist[*][?(@.name == 'name1')]'''
19 | JsonPath.builder().field("some").field("nested").array("withlist").contains("name").isEqualTo("name2").jsonPath() || '''$.some.nested.withlist[*][?(@.name == 'name2')]'''
20 | JsonPath.builder().field("some").field("nested").field("json").isEqualTo("with \"val'ue").jsonPath() || '''$.some.nested[?(@.json == 'with "val\\'ue')]'''
21 | JsonPath.builder().field("some", "nested", "json").isEqualTo("with \"val'ue").jsonPath() || '''$.some.nested[?(@.json == 'with "val\\'ue')]'''
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------