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