View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.bean.swagger.ui;
18  
19  import static org.apache.juneau.bean.swagger.SwaggerBuilder.*;
20  import static org.apache.juneau.commons.utils.CollectionUtils.*;
21  import static org.apache.juneau.junit.bct.BctAssertions.*;
22  import static org.junit.jupiter.api.Assertions.*;
23  
24  import java.util.*;
25  
26  import org.apache.juneau.*;
27  import org.junit.jupiter.api.*;
28  
29  /**
30   * Testcase for {@link SwaggerUI}.
31   */
32  class SwaggerUI_Test extends TestBase {
33  
34  	private final BeanSession bs = BeanContext.DEFAULT_SESSION;
35  
36  	/**
37  	 * Test method for media types.
38  	 */
39  	@Test void a01_mediaTypes() {
40  		assertList(
41  			new SwaggerUI().forMediaTypes(),
42  			"text/html"
43  		);
44  	}
45  
46  	/**
47  	 * Test method for basic Swagger document conversion.
48  	 */
49  	@Test void a02_basicSwaggerConversion() throws Exception {
50  		var swagger = swagger()
51  			.setInfo(info("Test API", "1.0.0").setDescription("Test API Description"))
52  			.setHost("localhost:8080")
53  			.setBasePath("/api")
54  			.setPaths(map("/test", operationMap().append("get", operation().setSummary("Test operation"))));
55  
56  		assertString(
57  			"""
58  			<div class='swagger-ui'>
59  				<style></style>
60  				<script type='text/javascript'><sp/></script>
61  				<table class='header'>
62  					<tr><th>Description:</th><td>Test API Description</td></tr>
63  					<tr><th>Version:</th><td>1.0.0</td></tr>
64  				</table>
65  				<div class='tag-block tag-block-open'>
66  					<div class='tag-block-contents'>
67  						<div class='op-block op-block-closed get'>
68  							<div class='op-block-summary' onclick='toggleOpBlock(this)'>
69  								<span class='method-button'>GET</span>
70  								<span class='path'>/test</span>
71  								<span class='summary'>Test operation</span>
72  							</div>
73  							<div class='op-block-contents'>
74  								<div class='table-container'></div>
75  							</div>
76  						</div>
77  					</div>
78  				</div>
79  			</div>
80  			""".replaceAll("\\n\\s*", ""),
81  			new SwaggerUI().swap(bs, swagger)
82  		);
83  	}
84  
85  	/**
86  	 * Test method for Swagger document with tags.
87  	 */
88  	@Test void a03_swaggerWithTags() throws Exception {
89  		var swagger = swagger()
90  			.setInfo(info("Test API", "1.0.0"))
91  			.setTags(l(
92  				tag("users").setDescription("User operations"),
93  				tag("orders").setDescription("Order operations")
94  			));
95  
96  		assertString(
97  			"""
98  			<div class='swagger-ui'>
99  				<style></style>
100 				<script type='text/javascript'><sp/></script>
101 				<table class='header'>
102 					<tr><th>Version:</th><td>1.0.0</td></tr>
103 				</table>
104 				<div class='tag-block tag-block-open'>
105 					<div class='tag-block-contents'></div>
106 				</div>
107 				<div class='tag-block tag-block-open'>
108 					<div class='tag-block-summary' onclick='toggleTagBlock(this)'>
109 						<span class='name'>users</span>
110 						<span class='description'>User operations</span>
111 					</div>
112 					<div class='tag-block-contents'></div>
113 				</div>
114 				<div class='tag-block tag-block-open'>
115 					<div class='tag-block-summary' onclick='toggleTagBlock(this)'>
116 						<span class='name'>orders</span>
117 						<span class='description'>Order operations</span>
118 					</div>
119 					<div class='tag-block-contents'></div>
120 				</div>
121 			</div>
122 			""".replaceAll("\\n\\s*", ""),
123 			new SwaggerUI().swap(bs, swagger)
124 		);
125 	}
126 
127 	/**
128 	 * Test method for Swagger document with parameters.
129 	 */
130 	@Test void a04_swaggerWithParameters() throws Exception {
131 		var swagger = swagger()
132 			.setInfo(info("Test API", "1.0.0"))
133 			.setPaths(new HashMap<>());
134 
135 		assertString(
136 			"""
137 			<div class='swagger-ui'>
138 				<style></style>
139 				<script type='text/javascript'><sp/></script>
140 				<table class='header'>
141 					<tr><th>Version:</th><td>1.0.0</td></tr>
142 				</table>
143 				<div class='tag-block tag-block-open'>
144 					<div class='tag-block-contents'></div>
145 				</div>
146 			</div>
147 			""".replaceAll("\\n\\s*", ""),
148 			new SwaggerUI().swap(bs, swagger)
149 		);
150 	}
151 
152 	/**
153 	 * Test method for Swagger document with responses.
154 	 */
155 	@Test void a05_swaggerWithResponses() throws Exception {
156 		var swagger = swagger()
157 			.setInfo(info("Test API", "1.0.0"))
158 			.setPaths(new HashMap<>());
159 
160 		assertString(
161 			"""
162 			<div class='swagger-ui'>
163 				<style></style>
164 				<script type='text/javascript'><sp/></script>
165 				<table class='header'>
166 					<tr><th>Version:</th><td>1.0.0</td></tr>
167 				</table>
168 				<div class='tag-block tag-block-open'>
169 					<div class='tag-block-contents'></div>
170 				</div>
171 			</div>
172 			""".replaceAll("\\n\\s*", ""),
173 			new SwaggerUI().swap(bs, swagger)
174 		);
175 	}
176 
177 	/**
178 	 * Test method for Swagger document with models.
179 	 */
180 	@Test void a06_swaggerWithModels() throws Exception {
181 		var swagger = swagger()
182 			.setInfo(info("Test API", "1.0.0"))
183 			.setPaths(new HashMap<>());
184 
185 		assertString(
186 			"""
187 			<div class='swagger-ui'>
188 				<style></style>
189 				<script type='text/javascript'><sp/></script>
190 				<table class='header'>
191 					<tr><th>Version:</th><td>1.0.0</td></tr>
192 				</table>
193 				<div class='tag-block tag-block-open'>
194 					<div class='tag-block-contents'></div>
195 				</div>
196 			</div>
197 			""".replaceAll("\\n\\s*", ""),
198 			new SwaggerUI().swap(bs, swagger)
199 		);
200 	}
201 
202 	/**
203 	 * Test method for empty Swagger document.
204 	 */
205 	@Test void a07_emptySwaggerDocument() throws Exception {
206 		var swagger = swagger()
207 			.setInfo(info("Test API", "1.0.0"))
208 			.setPaths(new HashMap<>());
209 
210 		assertString(
211 			"""
212 			<div class='swagger-ui'>
213 				<style></style>
214 				<script type='text/javascript'><sp/></script>
215 				<table class='header'>
216 					<tr><th>Version:</th><td>1.0.0</td></tr>
217 				</table>
218 				<div class='tag-block tag-block-open'>
219 					<div class='tag-block-contents'></div>
220 				</div>
221 			</div>
222 			""".replaceAll("\\n\\s*", ""),
223 			new SwaggerUI().swap(bs, swagger)
224 		);
225 	}
226 
227 	/**
228 	 * Test method for Swagger document with external documentation.
229 	 */
230 	@Test void a08_swaggerWithExternalDocs() throws Exception {
231 		var swagger = swagger()
232 			.setInfo(info("Test API", "1.0.0"))
233 			.setPaths(new HashMap<>());
234 
235 		assertString(
236 			"""
237 			<div class='swagger-ui'>
238 				<style></style>
239 				<script type='text/javascript'><sp/></script>
240 				<table class='header'>
241 					<tr><th>Version:</th><td>1.0.0</td></tr>
242 				</table>
243 				<div class='tag-block tag-block-open'>
244 					<div class='tag-block-contents'></div>
245 				</div>
246 			</div>
247 			""".replaceAll("\\n\\s*", ""),
248 			new SwaggerUI().swap(bs, swagger)
249 		);
250 	}
251 
252 	/**
253 	 * Test method for Swagger document with security schemes.
254 	 */
255 	@Test void a09_swaggerWithSecuritySchemes() throws Exception {
256 		var swagger = swagger()
257 			.setInfo(info("Test API", "1.0.0"))
258 			.setPaths(new HashMap<>());
259 
260 		assertString(
261 			"""
262 			<div class='swagger-ui'>
263 				<style></style>
264 				<script type='text/javascript'><sp/></script>
265 				<table class='header'>
266 					<tr><th>Version:</th><td>1.0.0</td></tr>
267 				</table>
268 				<div class='tag-block tag-block-open'>
269 					<div class='tag-block-contents'></div>
270 				</div>
271 			</div>
272 			""".replaceAll("\\n\\s*", ""),
273 			new SwaggerUI().swap(bs, swagger)
274 		);
275 	}
276 
277 	/**
278 	 * Test method for Swagger document with multiple operations.
279 	 */
280 	@Test void a10_swaggerWithMultipleOperations() throws Exception {
281 		var swagger = swagger()
282 			.setInfo(info("Test API", "1.0.0"))
283 			.setPaths(new HashMap<>());
284 
285 		assertString(
286 			"""
287 			<div class='swagger-ui'>
288 				<style></style>
289 				<script type='text/javascript'><sp/></script>
290 				<table class='header'>
291 					<tr><th>Version:</th><td>1.0.0</td></tr>
292 				</table>
293 				<div class='tag-block tag-block-open'>
294 					<div class='tag-block-contents'></div>
295 				</div>
296 			</div>
297 			""".replaceAll("\\n\\s*", ""),
298 			new SwaggerUI().swap(bs, swagger)
299 		);
300 	}
301 
302 	/**
303 	 * Test method for null input.
304 	 */
305 	@Test void a11_nullInput() {
306 		assertThrows(NullPointerException.class, () -> {
307 			new SwaggerUI().swap(bs, null);
308 		});
309 	}
310 
311 	/**
312 	 * Test method for HTML output structure.
313 	 */
314 	@Test void a12_htmlOutputStructure() throws Exception {
315 		var swagger = swagger()
316 			.setInfo(info("Test API", "1.0.0"))
317 			.setPaths(map("/test", operationMap()
318 				.append("get", operation().setSummary("Test operation"))));
319 
320 		assertString(
321 			"""
322 			<div class='swagger-ui'>
323 				<style></style>
324 				<script type='text/javascript'><sp/></script>
325 				<table class='header'>
326 					<tr><th>Version:</th><td>1.0.0</td></tr>
327 				</table>
328 				<div class='tag-block tag-block-open'>
329 					<div class='tag-block-contents'>
330 						<div class='op-block op-block-closed get'>
331 							<div class='op-block-summary' onclick='toggleOpBlock(this)'>
332 								<span class='method-button'>GET</span>
333 								<span class='path'>/test</span>
334 								<span class='summary'>Test operation</span>
335 							</div>
336 							<div class='op-block-contents'>
337 								<div class='table-container'></div>
338 							</div>
339 						</div>
340 					</div>
341 				</div>
342 			</div>
343 			""".replaceAll("\\n\\s*", ""),
344 			new SwaggerUI().swap(bs, swagger)
345 		);
346 	}
347 }