1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.bean.openapi3;
18
19 import static org.apache.juneau.TestUtils.*;
20 import static org.apache.juneau.bean.openapi3.OpenApiBuilder.*;
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 java.net.*;
26
27 import org.apache.juneau.*;
28 import org.junit.jupiter.api.*;
29
30
31
32
33 class OpenApi_Test extends TestBase {
34
35 @Nested class A_basicTests extends TestBase {
36
37 private static final BeanTester<OpenApi> TESTER =
38 testBean(
39 bean()
40 .setComponents(components().setSchemas(map("a1", schemaInfo().setType("a2"))))
41 .setExternalDocs(externalDocumentation().setUrl(URI.create("b")))
42 .setInfo(info().setTitle("c1").setVersion("c2"))
43 .setOpenapi("3.0.0")
44 .setPaths(map("d1", pathItem().setGet(operation().setSummary("d2"))))
45 .setSecurity(l(securityRequirement().setRequirements(map("e1",l("e2")))))
46 .setServers(l(server().setUrl(URI.create("f"))))
47 .setTags(l(tag().setName("g")))
48 )
49 .props("components{schemas{a1{type}}},externalDocs{url},info{title,version},openapi,paths{d1{get{summary}}},security{0{requirements{e1}}},servers{0{url}},tags{0{name}}")
50 .vals("{{{a2}}},{b},{c1,c2},3.0.0,{{{d2}}},{{{[e2]}}},{{f}},{{g}}")
51 .json("{components:{schemas:{a1:{type:'a2'}}},externalDocs:{url:'b'},info:{title:'c1',version:'c2'},openapi:'3.0.0',paths:{d1:{get:{summary:'d2'}}},security:[{requirements:{e1:['e2']}}],servers:[{url:'f'}],tags:[{name:'g'}]}")
52 .string("{'components':{'schemas':{'a1':{'type':'a2'}}},'externalDocs':{'url':'b'},'info':{'title':'c1','version':'c2'},'openapi':'3.0.0','paths':{'d1':{'get':{'summary':'d2'}}},'security':[{'requirements':{'e1':['e2']}}],'servers':[{'url':'f'}],'tags':[{'name':'g'}]}".replace('\'','"'))
53 ;
54
55 @Test void a01_gettersAndSetters() {
56 TESTER.assertGettersAndSetters();
57 }
58
59 @Test void a02_copy() {
60 TESTER.assertCopy();
61 }
62
63 @Test void a03_toJson() {
64 TESTER.assertToJson();
65 }
66
67 @Test void a04_fromJson() {
68 TESTER.assertFromJson();
69 }
70
71 @Test void a05_roundTrip() {
72 TESTER.assertRoundTrip();
73 }
74
75 @Test void a06_toString() {
76 TESTER.assertToString();
77 }
78
79 @Test void a07_keySet() {
80 assertList(TESTER.bean().keySet(), "components", "externalDocs", "info", "openapi", "paths", "security", "servers", "tags");
81 }
82
83 @Test void a08_nullParameters() {
84 var x = bean();
85 assertThrows(IllegalArgumentException.class, () -> x.get(null, String.class));
86 assertThrows(IllegalArgumentException.class, () -> x.set(null, "value"));
87 }
88
89 @Test void a09_addMethods() {
90 assertBean(
91 bean()
92 .addPath("/test", pathItem().setGet(operation().setSummary("a"))),
93 "paths{/test{get{summary}}}",
94 "{{{a}}}"
95 );
96
97
98 var x1 = bean()
99 .addTags(tag("b1"), tag("b2"))
100 .addTags(l(tag("b3")));
101 assertBean(x1, "tags{#{name}}", "{[{b1},{b2},{b3}]}");
102
103
104 var x2 = bean()
105 .addServers(server().setUrl(URI.create("http://c1.com")), server().setUrl(URI.create("http://c2.com")))
106 .addServers(l(server().setUrl(URI.create("http://c3.com"))));
107 assertBean(x2, "servers{#{url}}", "{[{http://c1.com},{http://c2.com},{http://c3.com}]}");
108
109
110 var x3 = bean()
111 .addSecurity(securityRequirement().setRequirements(map("d1", l("d2"))))
112 .addSecurity(l(securityRequirement().setRequirements(map("d3", l("d4")))));
113 assertBean(x3, "security{#{requirements}}", "{[{{d1=[d2]}},{{d3=[d4]}}]}");
114 }
115
116 @Test void a09b_setTagsVarargs() {
117
118 var x = bean().setTags(tag("t1"), tag("t2"), tag("t3"));
119 assertBean(x, "tags{#{name}}", "{[{t1},{t2},{t3}]}");
120 }
121
122 @Test void a10_asMap() {
123 assertBean(
124 bean()
125 .setInfo(info().setTitle("a1").setVersion("a2"))
126 .set("x1", "x1a")
127 .asMap(),
128 "info{title,version},openapi,x1",
129 "{a1,a2},3.0.0,x1a"
130 );
131 }
132
133 @Test void a11_extraKeys() {
134 var x = bean().set("x1", "x1a").set("x2", "x2a");
135 assertList(x.extraKeys(), "x1", "x2");
136 assertEmpty(bean().extraKeys());
137 }
138
139 @Test void a12_strictMode() {
140 assertThrows(RuntimeException.class, () -> bean().strict().set("foo", "bar"));
141 assertDoesNotThrow(() -> bean().set("foo", "bar"));
142
143 assertFalse(bean().isStrict());
144 assertTrue(bean().strict().isStrict());
145 assertFalse(bean().strict(false).isStrict());
146 }
147
148 @Test void a13_collectionSetters() {
149 var x = bean()
150 .setSecurity(l(securityRequirement().setRequirements(map("a1", l("a2"))), securityRequirement().setRequirements(map("b1", l("b2")))))
151 .setServers(l(server().setUrl(URI.create("http://example1.com")), server().setUrl(URI.create("http://example2.com"))))
152 .setTags(l(tag().setName("c1"), tag().setName("c2")));
153
154 assertBean(x,
155 "security{#{requirements}},servers{#{url}},tags{#{name}}",
156 "{[{{a1=[a2]}},{{b1=[b2]}}]},{[{http://example1.com},{http://example2.com}]},{[{c1},{c2}]}"
157 );
158 }
159
160 @Test void a14_addPath() {
161
162 var x = bean()
163 .addPath("/test", pathItem().setGet(operation().setSummary("Test operation")))
164 .addPath("/test2", pathItem().setPost(operation().setSummary("Test POST operation")));
165
166 assertBean(x,
167 "paths{/test{get{summary}},/test2{post{summary}}}",
168 "{{{Test operation}},{{Test POST operation}}}"
169 );
170
171
172 assertThrows(IllegalArgumentException.class, () -> x.addPath(null, pathItem()));
173 assertThrows(IllegalArgumentException.class, () -> x.addPath("/test", null));
174 }
175 }
176
177 @Nested class B_emptyTests extends TestBase {
178
179 private static final BeanTester<OpenApi> TESTER =
180 testBean(bean())
181 .props("openapi,info,externalDocs,servers,tags,paths,components,security")
182 .vals("3.0.0,<null>,<null>,<null>,<null>,<null>,<null>,<null>")
183 .json("{openapi:'3.0.0'}")
184 .string("{\"openapi\":\"3.0.0\"}")
185 ;
186
187 @Test void b01_gettersAndSetters() {
188 TESTER.assertGettersAndSetters();
189 }
190
191 @Test void b02_copy() {
192 TESTER.assertCopy();
193 }
194
195 @Test void b03_toJson() {
196 TESTER.assertToJson();
197 }
198
199 @Test void b04_fromJson() {
200 TESTER.assertFromJson();
201 }
202
203 @Test void b05_roundTrip() {
204 TESTER.assertRoundTrip();
205 }
206
207 @Test void b06_toString() {
208 TESTER.assertToString();
209 }
210
211 @Test void b07_keySet() {
212 assertList(TESTER.bean().keySet(), "openapi");
213 }
214
215 @Test void b08_keySet_infoNull() {
216
217 var x = bean().setOpenapi("3.0.0");
218 assertList(x.keySet(), "openapi");
219 assertFalse(x.keySet().contains("info"));
220 }
221 }
222
223 @Nested class C_extraProperties extends TestBase {
224 private static final BeanTester<OpenApi> TESTER =
225 testBean(
226 bean()
227 .set("components", components().setSchemas(map("a1", schemaInfo("a2"))))
228 .set("externalDocs", externalDocumentation().setUrl(URI.create("b")))
229 .set("info", info().setTitle("c").setVersion("d"))
230 .set("openapi", "e")
231 .set("paths", m("f1", pathItem().setGet(operation().setSummary("f2"))))
232 .set("security", l(securityRequirement().setRequirements(map("g1",l("g2")))))
233 .set("servers", l(server().setUrl(URI.create("h"))))
234 .set("tags", l(tag("i")))
235 .set("x1", "x1a")
236 .set("x2", null)
237 )
238 .props("components{schemas{a1{type}}},externalDocs{url},info{title,version},openapi,paths{f1{get{summary}}},security{#{requirements{g1{#{toString}}}}},servers{#{url}},tags{#{name}},x1,x2")
239 .vals("{{{a2}}},{b},{c,d},e,{{{f2}}},{[{{{[{g2}]}}}]},{[{h}]},{[{i}]},x1a,<null>")
240 .json("{components:{schemas:{a1:{type:'a2'}}},externalDocs:{url:'b'},info:{title:'c',version:'d'},openapi:'e',paths:{f1:{get:{summary:'f2'}}},security:[{requirements:{g1:['g2']}}],servers:[{url:'h'}],tags:[{name:'i'}],x1:'x1a'}")
241 .string("{'components':{'schemas':{'a1':{'type':'a2'}}},'externalDocs':{'url':'b'},'info':{'title':'c','version':'d'},'openapi':'e','paths':{'f1':{'get':{'summary':'f2'}}},'security':[{'requirements':{'g1':['g2']}}],'servers':[{'url':'h'}],'tags':[{'name':'i'}],'x1':'x1a'}".replace('\'', '"'))
242 ;
243
244 @Test void c01_gettersAndSetters() {
245 TESTER.assertGettersAndSetters();
246 }
247
248 @Test void c02_copy() {
249 TESTER.assertCopy();
250 }
251
252 @Test void c03_toJson() {
253 TESTER.assertToJson();
254 }
255
256 @Test void c04_fromJson() {
257 TESTER.assertFromJson();
258 }
259
260 @Test void c05_roundTrip() {
261 TESTER.assertRoundTrip();
262 }
263
264 @Test void c06_toString() {
265 TESTER.assertToString();
266 }
267
268 @Test void c07_keySet() {
269 assertList(TESTER.bean().keySet(), "components", "externalDocs", "info", "openapi", "paths", "security", "servers", "tags", "x1", "x2");
270 }
271
272 @Test void c08_get() {
273 assertMapped(
274 TESTER.bean(), (obj,prop) -> obj.get(prop, Object.class),
275 "components{schemas{a1{type}}},externalDocs{url},info{title,version},openapi,paths{f1{get{summary}}},security{#{requirements{g1{#{toString}}}}},servers{#{url}},tags{#{name}},x1,x2",
276 "{{{a2}}},{b},{c,d},e,{{{f2}}},{[{{{[{g2}]}}}]},{[{h}]},{[{i}]},x1a,<null>"
277 );
278 }
279
280 @Test void c09_getTypes() {
281 assertMapped(
282 TESTER.bean(), (obj,prop) -> cns(obj.get(prop, Object.class)),
283 "components,externalDocs,info,openapi,paths,security,servers,tags,x1,x2",
284 "Components,ExternalDocumentation,Info,String,FilteredMap,ArrayList,ArrayList,ArrayList,String,<null>"
285 );
286 }
287
288 @Test void c10_nullPropertyValue() {
289 assertThrows(IllegalArgumentException.class, ()->bean().get(null));
290 assertThrows(IllegalArgumentException.class, ()->bean().get(null, String.class));
291 assertThrows(IllegalArgumentException.class, ()->bean().set(null, "a"));
292 }
293 }
294
295 @Nested class D_utilityMethods extends TestBase {
296
297 @Test void d01_findRef() {
298 var x = openApi()
299 .setComponents(components().setSchemas(map("a1", schemaInfo().setType("a2"))));
300
301 assertBean(
302 x.findRef("#/components/schemas/a1", SchemaInfo.class),
303 "type",
304 "a2"
305 );
306
307 assertNull(x.findRef("#/components/schemas/notfound", SchemaInfo.class));
308
309 assertThrows(IllegalArgumentException.class, () -> x.findRef(null, SchemaInfo.class));
310 assertThrows(IllegalArgumentException.class, () -> x.findRef("a", null));
311 assertThrows(IllegalArgumentException.class, () -> x.findRef("", SchemaInfo.class));
312 assertThrowsWithMessage(RuntimeException.class, "Unsupported reference: 'invalid'", () -> x.findRef("invalid", SchemaInfo.class));
313 }
314 }
315
316
317
318
319
320 private static OpenApi bean() {
321 return openApi();
322 }
323 }