1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.bean.swagger;
18
19 import static org.apache.juneau.TestUtils.*;
20 import static org.apache.juneau.bean.swagger.SwaggerBuilder.*;
21 import static org.apache.juneau.commons.utils.CollectionUtils.*;
22 import static org.apache.juneau.junit.bct.BctAssertions.*;
23 import static org.junit.jupiter.api.Assertions.*;
24
25 import org.apache.juneau.*;
26 import org.apache.juneau.MediaType;
27 import org.apache.juneau.collections.*;
28 import org.junit.jupiter.api.*;
29
30
31
32
33 class Swagger_Test extends TestBase {
34
35 @Nested class A_basicTests extends TestBase {
36
37 private static final BeanTester<Swagger> TESTER =
38 testBean(
39 bean()
40 .setBasePath("a")
41 .setConsumes(MediaType.of("b"))
42 .setDefinitions(map("c1", JsonMap.of("type", "c2")))
43 .setExternalDocs(externalDocumentation("d"))
44 .setHost("e")
45 .setInfo(info("f1", "f2"))
46 .setParameters(map("g1", parameterInfo("g2", "g3")))
47 .setPaths(map("h1", operationMap().append("get", operation().setSummary("h2"))))
48 .setProduces(MediaType.of("i"))
49 .setResponses(map("j1", responseInfo().setDescription("j2")))
50 .setSchemes("k")
51 .setSecurity(l(map("l1", l("l2"))))
52 .setSecurityDefinitions(map("m1", securityScheme().setType("m2")))
53 .setSwagger("n")
54 .setTags(tag().setName("o"))
55 )
56 .props("basePath,consumes,definitions{c1{type}},externalDocs{url},host,info{title,version},parameters{g1{in,name}},paths{h1{get{summary}}},produces,responses{j1{description}},schemes,security{0{l1}},securityDefinitions{m1{type}},swagger,tags{0{name}}")
57 .vals("a,[b],{{c2}},{d},e,{f1,f2},{{g2,g3}},{{{h2}}},[i],{{j2}},[k],{{[l2]}},{{m2}},n,{{o}}")
58 .json("{basePath:'a',consumes:['b'],definitions:{c1:{type:'c2'}},externalDocs:{url:'d'},host:'e',info:{title:'f1',version:'f2'},parameters:{g1:{'in':'g2',name:'g3'}},paths:{h1:{get:{summary:'h2'}}},produces:['i'],responses:{j1:{description:'j2'}},schemes:['k'],security:[{l1:['l2']}],securityDefinitions:{m1:{type:'m2'}},swagger:'n',tags:[{name:'o'}]}")
59 .string("{'basePath':'a','consumes':['b'],'definitions':{'c1':{'type':'c2'}},'externalDocs':{'url':'d'},'host':'e','info':{'title':'f1','version':'f2'},'parameters':{'g1':{'in':'g2','name':'g3'}},'paths':{'h1':{'get':{'summary':'h2'}}},'produces':['i'],'responses':{'j1':{'description':'j2'}},'schemes':['k'],'security':[{'l1':['l2']}],'securityDefinitions':{'m1':{'type':'m2'}},'swagger':'n','tags':[{'name':'o'}]}".replace('\'', '"'))
60 ;
61
62 @Test void a01_gettersAndSetters() {
63 TESTER.assertGettersAndSetters();
64 }
65
66 @Test void a02_copy() {
67 TESTER.assertCopy();
68 }
69
70 @Test void a03_toJson() {
71 TESTER.assertToJson();
72 }
73
74 @Test void a04_fromJson() {
75 TESTER.assertFromJson();
76 }
77
78 @Test void a05_roundTrip() {
79 TESTER.assertRoundTrip();
80 }
81
82 @Test void a06_toString() {
83 TESTER.assertToString();
84 }
85
86 @Test void a07_keySet() {
87 assertList(TESTER.bean().keySet(), "basePath", "consumes", "definitions", "externalDocs", "host", "info", "parameters", "paths", "produces", "responses", "schemes", "security", "securityDefinitions", "swagger", "tags");
88 }
89
90 @Test void a08_otherGettersAndSetters() {
91
92 var x = bean()
93 .addPath("a1", "get", operation().setSummary("a2"))
94 .addPath("b1", "get", operation().addResponse("200", responseInfo("b2")).setParameters(parameterInfo("b3", "b4")))
95 .addParameter("c1", parameterInfo("c2", "c3"));
96
97 assertBean(x.getPath("a1"), "get{summary}", "{a2}");
98 assertBean(x.getOperation("a1", "get"), "summary", "a2");
99 assertBean(x.getResponseInfo("b1", "get", "200"), "description", "b2");
100 assertBean(x.getResponseInfo("b1", "get", 200), "description", "b2");
101 assertBean(x.getParameterInfo("b1", "get", "b3", "b4"), "in,name", "b3,b4");
102
103
104 x = bean()
105 .setConsumes(MediaType.of("e1"), MediaType.of("e2"))
106 .setProduces(MediaType.of("f1"), MediaType.of("f2"))
107 .setSchemes("g1", "g2");
108
109 assertBean(x, "consumes,produces,schemes", "[e1,e2],[f1,f2],[g1,g2]");
110 }
111
112 @Test void a09_nullParameters() {
113 var x = bean();
114
115 assertThrows(IllegalArgumentException.class, ()->x.getPath(null));
116 assertThrows(IllegalArgumentException.class, ()->x.getOperation(null, "a"));
117 assertThrows(IllegalArgumentException.class, ()->x.getOperation("a", null));
118 assertThrows(IllegalArgumentException.class, ()->x.getResponseInfo(null, "a", "a"));
119 assertThrows(IllegalArgumentException.class, ()->x.getResponseInfo("a", null, "a"));
120 assertThrows(IllegalArgumentException.class, ()->x.getResponseInfo("a", "a", null));
121 assertThrows(IllegalArgumentException.class, ()->x.getParameterInfo(null, "a", "a", "a"));
122 assertThrows(IllegalArgumentException.class, ()->x.getParameterInfo("a", null, "a", "a"));
123 assertThrows(IllegalArgumentException.class, ()->x.getParameterInfo("a", "a", null, "a"));
124 assertThrows(IllegalArgumentException.class, ()->x.get(null, String.class));
125 assertThrows(IllegalArgumentException.class, ()->x.set(null, "value"));
126 assertThrows(IllegalArgumentException.class, ()->x.addDefinition(null, JsonMap.of("a", "b")));
127 assertThrows(IllegalArgumentException.class, ()->x.addDefinition("a", null));
128 assertThrows(IllegalArgumentException.class, ()->x.addParameter(null, parameterInfo("a", "b")));
129 assertThrows(IllegalArgumentException.class, ()->x.addParameter("a", null));
130 assertThrows(IllegalArgumentException.class, ()->x.addPath(null, "get", operation()));
131 assertThrows(IllegalArgumentException.class, ()->x.addPath("a", null, operation()));
132 assertThrows(IllegalArgumentException.class, ()->x.addPath("a", "get", null));
133 assertThrows(IllegalArgumentException.class, ()->x.addResponse(null, responseInfo()));
134 assertThrows(IllegalArgumentException.class, ()->x.addResponse("a", null));
135 assertThrows(IllegalArgumentException.class, ()->x.addSecurity(null, "a"));
136 assertThrows(IllegalArgumentException.class, ()->x.addSecurityDefinition(null, securityScheme()));
137 assertThrows(IllegalArgumentException.class, ()->x.addSecurityDefinition("a", null));
138 }
139
140 @Test void a10_collectionSetters() {
141
142 var x = bean()
143 .setConsumes(l(
144 MediaType.of("a1"),
145 MediaType.of("a2")
146 ))
147 .setProduces(l(
148 MediaType.of("b1"),
149 MediaType.of("b2")
150 ))
151 .setSchemes(l("c1", "c2"))
152 .setTags(l(tag().setName("d1"), tag().setName("d2")))
153 .setSecurity(l(
154 m("e1", l("e2")),
155 m("e3", l("e4"))
156 ));
157
158 assertBean(x,
159 "consumes,produces,schemes,tags{0{name},1{name}},security{0{e1},1{e3}}",
160 "[a1,a2],[b1,b2],[c1,c2],{{d1},{d2}},{{[e2]},{[e4]}}"
161 );
162 }
163
164 @Test void a11_varargAdders() {
165
166 var x = bean()
167 .addConsumes(MediaType.of("a1"))
168 .addConsumes(MediaType.of("a2"))
169 .addProduces(MediaType.of("b1"))
170 .addProduces(MediaType.of("b2"))
171 .addSchemes("c1")
172 .addSchemes("c2")
173 .addTags(tag().setName("d1"))
174 .addTags(tag().setName("d2"));
175
176 assertBean(x,
177 "consumes,produces,schemes,tags{0{name},1{name}}",
178 "[a1,a2],[b1,b2],[c1,c2],{{d1},{d2}}"
179 );
180 }
181
182 @Test void a12_collectionAdders() {
183
184 var x = bean()
185 .addConsumes(l(MediaType.of("a1")))
186 .addConsumes(l(MediaType.of("a2")))
187 .addProduces(l(MediaType.of("b1")))
188 .addProduces(l(MediaType.of("b2")))
189 .addSchemes(l("c1"))
190 .addSchemes(l("c2"))
191 .addSecurity(l(map("d1",l("d2"))))
192 .addSecurity(l(map("d3",l("d4"))))
193 .addTags(l(tag().setName("e1")))
194 .addTags(l(tag().setName("e2")));
195
196 assertBean(x,
197 "consumes,produces,schemes,security,tags{0{name},1{name}}",
198 "[a1,a2],[b1,b2],[c1,c2],[{d1=[d2]},{d3=[d4]}],{{e1},{e2}}"
199 );
200 }
201
202 @Test void a13_asMap() {
203 assertBean(
204 bean()
205 .setBasePath("a")
206 .setHost("b")
207 .set("x1", "x1a")
208 .asMap(),
209 "basePath,host,swagger,x1",
210 "a,b,2.0,x1a"
211 );
212 }
213
214 @Test void a14_extraKeys() {
215 var x = bean().set("x1", "x1a").set("x2", "x2a");
216 assertList(x.extraKeys(), "x1", "x2");
217 assertEmpty(bean().extraKeys());
218 }
219
220 @Test void a15_addResponse() {
221
222 var x = bean()
223 .addResponse("200", responseInfo().setDescription("a"))
224 .addResponse("404", responseInfo().setDescription("b"));
225
226 assertBean(x,
227 "responses{200{description},404{description}}",
228 "{{a},{b}}"
229 );
230 }
231
232 @Test void a16_addSecurity() {
233
234 var x = bean()
235 .addSecurity("scheme1", "a", "b")
236 .addSecurity("scheme2", "c");
237
238 assertBean(x,
239 "security{0{scheme1},1{scheme2}}",
240 "{{[a,b]},{[c]}}"
241 );
242 }
243
244 @Test void a17_addSecurityDefinition() {
245
246 var x = bean()
247 .addSecurityDefinition("def1", securityScheme().setType("a"))
248 .addSecurityDefinition("def2", securityScheme().setType("b"));
249
250 assertBean(x,
251 "securityDefinitions{def1{type},def2{type}}",
252 "{{a},{b}}"
253 );
254 }
255
256 @Test void a18_getOperationNullPath() {
257 var a = swagger()
258 .addPath("/existing", "get", operation().setSummary("test"));
259
260
261 assertNull(a.getOperation("/nonexistent", "get"));
262
263
264 assertNull(a.getResponseInfo("/nonexistent", "get", "200"));
265
266
267 assertNull(a.getResponseInfo("/test", "post", "200"));
268
269
270 assertNull(a.getParameterInfo("/nonexistent", "get", "query", "param"));
271
272
273 assertNull(a.getParameterInfo("/test", "post", "query", "param"));
274 }
275
276 @Test void a19_getMethodWithInvalidProperty() {
277 var a = swagger();
278
279
280 assertNull(a.get("invalidProperty", String.class));
281 }
282
283 @Test void a20_strictMode() {
284 assertThrows(RuntimeException.class, () -> bean().strict().set("foo", "bar"));
285 assertDoesNotThrow(() -> bean().set("foo", "bar"));
286
287 assertFalse(bean().isStrict());
288 assertTrue(bean().strict().isStrict());
289 assertFalse(bean().strict(false).isStrict());
290 }
291
292 @Test void a21_asJson() {
293 var x = swagger().setHost("a");
294 var json = x.asJson();
295 assertTrue(json.contains("a"));
296 }
297 }
298
299 @Nested class B_emptyTests extends TestBase {
300
301 private static final BeanTester<Swagger> TESTER =
302 testBean(bean())
303 .props("basePath,host,swagger,info,tags,schemes,consumes,produces,paths,definitions,parameters,responses,securityDefinitions,security,externalDocs")
304 .vals("<null>,<null>,2.0,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>")
305 .json("{swagger:'2.0'}")
306 .string("{\"swagger\":\"2.0\"}")
307 ;
308
309 @Test void b01_gettersAndSetters() {
310 TESTER.assertGettersAndSetters();
311 }
312
313 @Test void b02_copy() {
314 TESTER.assertCopy();
315 }
316
317 @Test void b03_toJson() {
318 TESTER.assertToJson();
319 }
320
321 @Test void b04_fromJson() {
322 TESTER.assertFromJson();
323 }
324
325 @Test void b05_roundTrip() {
326 TESTER.assertRoundTrip();
327 }
328
329 @Test void b06_toString() {
330 TESTER.assertToString();
331 }
332
333 @Test void b07_keySet() {
334 assertList(TESTER.bean().keySet(), "swagger");
335 assertList(TESTER.bean().setSwagger(null).keySet());
336 }
337 }
338
339 @Nested class C_extraProperties extends TestBase {
340
341 private static final BeanTester<Swagger> TESTER =
342 testBean(
343 bean()
344 .set("basePath", "a")
345 .set("consumes", l(MediaType.of("b")))
346 .set("definitions", m("c1", JsonMap.of("type", "c2")))
347 .set("externalDocs", externalDocumentation("d"))
348 .set("host", "e")
349 .set("info", info("f1", "f2"))
350 .set("parameters", m("g1", parameterInfo("g2", "g3")))
351 .set("paths", m("h1", operationMap().append("get", operation().setSummary("h2"))))
352 .set("produces", l(MediaType.of("i")))
353 .set("responses", m("j1", responseInfo().setDescription("j2")))
354 .set("schemes", l("k"))
355 .set("security", l(m("l1", l("l2"))))
356 .set("securityDefinitions", m("m1", securityScheme().setType("m2")))
357 .set("swagger", "n")
358 .set("tags", l(tag().setName("o")))
359 .set("x1", "x1a")
360 .set("x2", null)
361 )
362 .props("basePath,consumes,definitions{c1{type}},externalDocs{url},host,info{title,version},parameters{g1{in,name}},paths{h1{get{summary}}},produces,responses{j1{description}},schemes,security{0{l1}},securityDefinitions{m1{type}},swagger,tags{0{name}},x1,x2")
363 .vals("a,[b],{{c2}},{d},e,{f1,f2},{{g2,g3}},{{{h2}}},[i],{{j2}},[k],{{[l2]}},{{m2}},n,{{o}},x1a,<null>")
364 .json("{basePath:'a',consumes:['b'],definitions:{c1:{type:'c2'}},externalDocs:{url:'d'},host:'e',info:{title:'f1',version:'f2'},parameters:{g1:{'in':'g2',name:'g3'}},paths:{h1:{get:{summary:'h2'}}},produces:['i'],responses:{j1:{description:'j2'}},schemes:['k'],security:[{l1:['l2']}],securityDefinitions:{m1:{type:'m2'}},swagger:'n',tags:[{name:'o'}],x1:'x1a'}")
365 .string("{'basePath':'a','consumes':['b'],'definitions':{'c1':{'type':'c2'}},'externalDocs':{'url':'d'},'host':'e','info':{'title':'f1','version':'f2'},'parameters':{'g1':{'in':'g2','name':'g3'}},'paths':{'h1':{'get':{'summary':'h2'}}},'produces':['i'],'responses':{'j1':{'description':'j2'}},'schemes':['k'],'security':[{'l1':['l2']}],'securityDefinitions':{'m1':{'type':'m2'}},'swagger':'n','tags':[{'name':'o'}],'x1':'x1a'}".replace('\'', '"'))
366 ;
367
368 @Test void c01_gettersAndSetters() {
369 TESTER.assertGettersAndSetters();
370 }
371
372 @Test void c02_copy() {
373 TESTER.assertCopy();
374 }
375
376 @Test void c03_toJson() {
377 TESTER.assertToJson();
378 }
379
380 @Test void c04_fromJson() {
381 TESTER.assertFromJson();
382 }
383
384 @Test void c05_roundTrip() {
385 TESTER.assertRoundTrip();
386 }
387
388 @Test void c06_toString() {
389 TESTER.assertToString();
390 }
391
392 @Test void c07_keySet() {
393 assertList(TESTER.bean().keySet(), "basePath", "consumes", "definitions", "externalDocs", "host", "info", "parameters", "paths", "produces", "responses", "schemes", "security", "securityDefinitions", "swagger", "tags", "x1", "x2");
394 }
395
396 @Test void c08_get() {
397 assertMapped(
398 TESTER.bean(), (obj,prop) -> obj.get(prop, Object.class),
399 "basePath,consumes,definitions{c1{type}},externalDocs{url},host,info{title,version},parameters{g1{in,name}},paths{h1{get{summary}}},produces,responses{j1{description}},schemes,security{0{l1}},securityDefinitions{m1{type}},swagger,tags{0{name}},x1,x2",
400 "a,[b],{{c2}},{d},e,{f1,f2},{{g2,g3}},{{{h2}}},[i],{{j2}},[k],{{[l2]}},{{m2}},n,{{o}},x1a,<null>"
401 );
402 }
403
404 @Test void c09_getTypes() {
405 assertMapped(
406 TESTER.bean(), (obj,prop) -> cns(obj.get(prop, Object.class)),
407 "basePath,consumes,definitions,externalDocs,host,info,parameters,paths,produces,responses,schemes,security,securityDefinitions,swagger,tags,x1,x2",
408 "String,LinkedHashSet,LinkedHashMap,ExternalDocumentation,String,Info,LinkedHashMap,TreeMap,LinkedHashSet,LinkedHashMap,LinkedHashSet,ArrayList,LinkedHashMap,String,LinkedHashSet,String,<null>"
409 );
410 }
411
412 @Test void c10_nullPropertyValue() {
413 assertThrows(IllegalArgumentException.class, ()->bean().get(null));
414 assertThrows(IllegalArgumentException.class, ()->bean().get(null, String.class));
415 assertThrows(IllegalArgumentException.class, ()->bean().set(null, "a"));
416 }
417 }
418
419 @Nested class D_refs extends TestBase {
420
421 @Test void d01_findRef() {
422 var x = swagger().addDefinition("a1", JsonMap.of("type", "a2"));
423 assertBean(
424 x.findRef("#/definitions/a1", JsonMap.class),
425 "type",
426 "a2"
427 );
428
429 assertNull(x.findRef("#/definitions/notfound", JsonMap.class));
430
431 assertThrows(IllegalArgumentException.class, () -> x.findRef(null, JsonMap.class));
432 assertThrows(IllegalArgumentException.class, () -> x.findRef("a", null));
433 assertThrows(IllegalArgumentException.class, () -> x.findRef("", JsonMap.class));
434 assertThrowsWithMessage(RuntimeException.class, "Unsupported reference: 'invalid'", () -> x.findRef("invalid", JsonMap.class));
435 }
436
437 @Test void d02_findRefInvalidType() {
438
439 var x = swagger()
440 .addDefinition("Pet", JsonMap.of("type", "object"))
441 .addResponse("Error", responseInfo().setDescription("Error response"))
442 .addParameter("petId", parameterInfo("path", "id"));
443
444
445 assertThrows(Exception.class, () -> x.findRef("#/definitions/Pet", Integer.class));
446
447
448 assertThrows(Exception.class, () -> x.findRef("#/responses/Error", Integer.class));
449
450
451 assertThrows(Exception.class, () -> x.findRef("#/parameters/petId", Integer.class));
452 }
453
454 }
455
456
457
458
459
460 private static Swagger bean() {
461 return swagger();
462 }
463 }