|
9 | 9 | */ |
10 | 10 | package org.openmrs.module.webservices.rest.doc; |
11 | 11 |
|
12 | | -import com.fasterxml.jackson.databind.ObjectMapper; |
13 | | -import io.swagger.converter.ModelConverterContextImpl; |
14 | 12 | import io.swagger.converter.ModelConverters; |
15 | | -import io.swagger.jackson.ModelResolver; |
16 | 13 | import io.swagger.models.Info; |
17 | 14 | import io.swagger.models.Model; |
18 | 15 | import io.swagger.models.ModelImpl; |
|
28 | 25 | import io.swagger.models.properties.RefProperty; |
29 | 26 | import io.swagger.models.properties.StringProperty; |
30 | 27 | import io.swagger.util.Json; |
31 | | -import org.dbunit.database.DatabaseConnection; |
32 | 28 | import org.junit.Assert; |
33 | 29 | import org.junit.Before; |
34 | 30 | import org.junit.Test; |
|
49 | 45 | import java.lang.reflect.Field; |
50 | 46 | import java.lang.reflect.InvocationTargetException; |
51 | 47 | import java.lang.reflect.Method; |
52 | | -import java.sql.Connection; |
53 | | -import java.sql.DatabaseMetaData; |
54 | | -import java.sql.ResultSet; |
55 | 48 | import java.util.ArrayList; |
56 | | -import java.util.HashMap; |
57 | 49 | import java.util.List; |
58 | 50 | import java.util.Map; |
59 | 51 |
|
60 | | -import static junit.framework.TestCase.assertFalse; |
61 | | -import static junit.framework.TestCase.assertNotNull; |
62 | 52 | import static junit.framework.TestCase.assertTrue; |
63 | 53 | import static org.junit.Assert.assertEquals; |
| 54 | +import static org.junit.Assert.assertFalse; |
| 55 | +import static org.junit.Assert.assertNotNull; |
64 | 56 |
|
65 | 57 | public class SwaggerSpecificationCreatorTest extends BaseModuleWebContextSensitiveTest { |
66 | | - |
| 58 | + private SwaggerSpecificationCreator swaggerCreator; |
| 59 | + |
| 60 | + @Before |
| 61 | + public void setUp() { |
| 62 | + Context.getService(RestService.class).initialize(); |
| 63 | + Context.getAdministrationService().saveGlobalProperty( |
| 64 | + new GlobalProperty(RestConstants.SWAGGER_QUIET_DOCS_GLOBAL_PROPERTY_NAME, "true")); |
| 65 | + Context.flushSession(); |
| 66 | + swaggerCreator = new SwaggerSpecificationCreator(); |
| 67 | + } |
| 68 | + |
67 | 69 | @Test |
68 | | - public void mainTest() { |
69 | | - String str = new SwaggerSpecificationCreator().getJSON(); |
70 | | - assertNotNull(str); |
| 70 | + public void getJSON_shouldGenerateSwaggerJSON() { |
| 71 | + assertNotNull(swaggerCreator.getJSON()); |
71 | 72 | } |
72 | | - |
| 73 | + |
73 | 74 | @Test |
74 | | - public void hasSearchHandler() { |
75 | | - SwaggerSpecificationCreator creator = new SwaggerSpecificationCreator(); |
76 | | - |
77 | | - assertTrue(creator.hasSearchHandler("attribute", "location")); |
78 | | - |
79 | | - assertFalse(creator.hasSearchHandler("workflow", null)); |
80 | | - assertFalse(creator.hasSearchHandler("description", "concept")); |
| 75 | + public void hasSearchHandler_shouldCheckSearchHandlerAvailability() { |
| 76 | + assertTrue(swaggerCreator.hasSearchHandler("attribute", "location")); |
| 77 | + assertFalse(swaggerCreator.hasSearchHandler("workflow", null)); |
81 | 78 | } |
82 | | - |
| 79 | + |
83 | 80 | @Test |
84 | | - public void cacheTest() { |
85 | | - if (SwaggerSpecificationCreator.isCached()) { |
86 | | - SwaggerSpecificationCreator.clearCache(); |
87 | | - } |
| 81 | + public void isCached_shouldCacheSwaggerSpecification() { |
| 82 | + SwaggerSpecificationCreator.clearCache(); |
88 | 83 | assertFalse(SwaggerSpecificationCreator.isCached()); |
89 | | - new SwaggerSpecificationCreator().getJSON(); |
| 84 | + swaggerCreator.getJSON(); |
90 | 85 | assertTrue(SwaggerSpecificationCreator.isCached()); |
91 | 86 | } |
92 | | - |
93 | | - @Test |
94 | | - public void modelResolveTest() { |
95 | | - final ModelResolver modelResolver = new ModelResolver(new ObjectMapper()); |
96 | | - final ModelConverterContextImpl context = new ModelConverterContextImpl(modelResolver); |
97 | | - final Model model = context.resolve(Patient.class); |
98 | | - assertNotNull(model); |
99 | | - } |
100 | | - |
101 | | - @Test |
102 | | - public void swaggerSerializeTest() { |
103 | | - final Info info = new Info().version("1.0.0").title("Swagger WebServices REST"); |
104 | | - |
105 | | - Swagger swagger = new Swagger().info(info).securityDefinition("basicAuth", new BasicAuthDefinition()) |
106 | | - .scheme(Scheme.HTTP).consumes("application/json").produces("application/json"); |
107 | | - |
108 | | - final Model patientModel = ModelConverters.getInstance().read(Patient.class).get("Patient"); |
109 | | - swagger.addDefinition("Patient", patientModel); |
110 | | - |
111 | | - final String swaggerJson = Json.pretty(swagger); |
112 | | - assertNotNull(swaggerJson); |
113 | | - } |
114 | | - |
115 | | - Map<String, Integer> beforeCounts; |
116 | | - |
117 | | - public Map<String, Integer> getRowCounts() throws Exception { |
118 | | - Map<String, Integer> ret = new HashMap<String, Integer>(); |
119 | | - |
120 | | - Connection con = this.getConnection(); |
121 | | - DatabaseMetaData metaData = con.getMetaData(); |
122 | | - DatabaseConnection dbcon = new DatabaseConnection(con); |
123 | | - |
124 | | - ResultSet rs = metaData.getTables(null, "PUBLIC", "%", null); |
125 | | - while (rs.next()) { |
126 | | - String tableName = rs.getString(3); |
127 | | - |
128 | | - ret.put(tableName, dbcon.getRowCount(tableName)); |
129 | | - } |
130 | | - |
131 | | - return ret; |
132 | | - } |
133 | | - |
134 | | - @Before |
135 | | - public void init() throws Exception { |
136 | | - // init REST |
137 | | - Context.getService(RestService.class).initialize(); |
138 | | - |
139 | | - Context.getAdministrationService().saveGlobalProperty( |
140 | | - new GlobalProperty(RestConstants.SWAGGER_QUIET_DOCS_GLOBAL_PROPERTY_NAME, "true")); |
141 | | - |
142 | | - // ensure GP is written to database before we count the rows |
143 | | - Context.flushSession(); |
144 | | - |
145 | | - beforeCounts = getRowCounts(); |
146 | | - } |
147 | | - |
| 87 | + |
148 | 88 | @Test |
149 | | - public void checkNoDatabaseChanges() throws Exception { |
150 | | - SwaggerSpecificationCreator ssc = new SwaggerSpecificationCreator(); |
151 | | - ssc.getJSON(); |
152 | | - |
153 | | - Map<String, Integer> afterCounts = getRowCounts(); |
154 | | - |
155 | | - Assert.assertEquals("Ensure no tables are created or destroyed", beforeCounts.size(), afterCounts.size()); |
156 | | - Assert.assertTrue("Ensure that no data was added or removed from any tables", |
157 | | - ensureCountsEqual(beforeCounts, afterCounts)); |
158 | | - } |
159 | | - |
160 | | - private boolean ensureCountsEqual(Map<String, Integer> beforeCounts, Map<String, Integer> afterCounts) { |
161 | | - for (String key : beforeCounts.keySet()) { |
162 | | - if (beforeCounts.get(key) != afterCounts.get(key)) { |
163 | | - System.err.println("The " + key + " table has a different number of rows (" + beforeCounts.get(key) |
164 | | - + " before, " + afterCounts.get(key) + " after)."); |
165 | | - |
166 | | - return false; |
167 | | - } |
168 | | - } |
169 | | - |
170 | | - return true; |
| 89 | + public void serializeSwagger_shouldSerializeSwagger() { |
| 90 | + Swagger swagger = new Swagger() |
| 91 | + .info(new Info().version("1.0.0").title("Swagger API")) |
| 92 | + .securityDefinition("basicAuth", new BasicAuthDefinition()) |
| 93 | + .scheme(Scheme.HTTP) |
| 94 | + .consumes("application/json") |
| 95 | + .produces("application/json"); |
| 96 | + |
| 97 | + swagger.addDefinition("Patient", ModelConverters.getInstance().read(Patient.class).get("Patient")); |
| 98 | + assertNotNull(Json.pretty(swagger)); |
171 | 99 | } |
172 | | - |
173 | | - // makes sure that every operation has a unique operationId |
| 100 | + |
174 | 101 | @Test |
175 | | - public void checkOperationIdsSet() { |
176 | | - List<String> operationIds = new ArrayList<String>(); |
177 | | - |
178 | | - SwaggerSpecificationCreator ssc = new SwaggerSpecificationCreator(); |
179 | | - ssc.getJSON(); |
180 | | - Swagger spec = ssc.getSwagger(); |
181 | | - |
182 | | - for (Path p : spec.getPaths().values()) { |
| 102 | + public void getOperationIds_shouldBeUnique() { |
| 103 | + swaggerCreator.getJSON(); |
| 104 | + Set<String> operationIds = new HashSet<>(); |
| 105 | + for (Path p : swaggerCreator.getSwagger().getPaths().values()) { |
183 | 106 | for (Operation o : p.getOperations()) { |
184 | | - Assert.assertFalse("Ensure each operation has a unique ID", operationIds.contains(o.getOperationId())); |
185 | | - operationIds.add(o.getOperationId()); |
| 107 | + assertTrue("Duplicate operationId found: " + o.getOperationId(), operationIds.add(o.getOperationId())); |
186 | 108 | } |
187 | 109 | } |
188 | 110 | } |
189 | | - |
190 | | - // makes sure that every GET operation has the "v" parameter |
| 111 | + |
191 | 112 | @Test |
192 | | - public void checkRepresentationParamExists() { |
193 | | - SwaggerSpecificationCreator ssc = new SwaggerSpecificationCreator(); |
194 | | - ssc.getJSON(); |
195 | | - Swagger spec = ssc.getSwagger(); |
196 | | - |
197 | | - for (Path p : spec.getPaths().values()) { |
198 | | - if (p.getGet() != null) { |
199 | | - Assert.assertTrue("Ensure each GET operation has the 'v' query parameter", |
200 | | - operationHasRepresentationParam(p.getGet())); |
| 113 | + public void getOperations_shouldHaveRepresentationParam() { |
| 114 | + swaggerCreator.getJSON(); |
| 115 | + for (Path path : swaggerCreator.getSwagger().getPaths().values()) { |
| 116 | + if (path.getGet() != null) { |
| 117 | + assertTrue(path.getGet().getParameters().stream().anyMatch(p -> "v".equals(p.getName()))); |
201 | 118 | } |
202 | 119 | } |
203 | 120 | } |
204 | | - |
205 | | - private boolean operationHasRepresentationParam(Operation o) { |
206 | | - boolean ret = false; |
207 | | - |
208 | | - for (Parameter p : o.getParameters()) { |
209 | | - if (p.getName().equals("v")) { |
210 | | - ret = !ret; |
211 | | - } |
212 | | - } |
213 | | - |
214 | | - return ret; |
215 | | - } |
216 | | - |
217 | | - // make sure each operation that supports paging has the limit and startIndex parameters |
| 121 | + |
218 | 122 | @Test |
219 | | - public void checkPagingParamsExist() { |
220 | | - SwaggerSpecificationCreator ssc = new SwaggerSpecificationCreator(); |
221 | | - ssc.getJSON(); |
222 | | - Swagger spec = ssc.getSwagger(); |
223 | | - |
224 | | - for (Path p : spec.getPaths().values()) { |
225 | | - for (Operation o : p.getOperations()) { |
226 | | - if (o.getOperationId().matches("^getAll[A-Z].*")) { |
227 | | - Assert.assertTrue("Ensure each operation that supports paging has both paging parameters", |
228 | | - operationHasPagingParams(o)); |
| 123 | + public void getAllOperations_shouldHavePagingParameters() { |
| 124 | + swaggerCreator.getJSON(); |
| 125 | + for (Path path : swaggerCreator.getSwagger().getPaths().values()) { |
| 126 | + for (Operation op : path.getOperations()) { |
| 127 | + if (op.getOperationId().startsWith("getAll")) { |
| 128 | + List<String> paramNames = new ArrayList<>(); |
| 129 | + for (Parameter param : op.getParameters()) { |
| 130 | + paramNames.add(param.getName()); |
| 131 | + } |
| 132 | + assertTrue(paramNames.containsAll(Arrays.asList("limit", "startIndex"))); |
229 | 133 | } |
230 | 134 | } |
231 | 135 | } |
232 | 136 | } |
233 | | - |
234 | | - private boolean operationHasPagingParams(Operation o) { |
235 | | - boolean limit = false, startIndex = false; |
236 | | - |
237 | | - for (Parameter p : o.getParameters()) { |
238 | | - if (p.getName().equals("limit")) { |
239 | | - limit = !limit; |
240 | | - } else if (p.getName().equals("startIndex")) { |
241 | | - startIndex = !startIndex; |
242 | | - } |
243 | | - } |
244 | | - |
245 | | - return limit && startIndex; |
246 | | - } |
247 | | - |
| 137 | + |
248 | 138 | @Test |
249 | | - public void addPathsWorksForCoreModels() throws NoSuchMethodException, InvocationTargetException, |
250 | | - IllegalAccessException, NoSuchFieldException { |
251 | | - SwaggerSpecificationCreator ssc = new SwaggerSpecificationCreator(); |
252 | | - |
253 | | - // reflect the swagger propperty and initSwagger method so we can setup for the main test |
254 | | - Field swagger = ssc.getClass().getDeclaredField("swagger"); |
| 139 | + public void addPaths_shouldWorkForCoreModels() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException { |
| 140 | + Field swagger = swaggerCreator.getClass().getDeclaredField("swagger"); |
255 | 141 | swagger.setAccessible(true); |
256 | | - swagger.set(ssc, new Swagger()); |
257 | | - |
258 | | - Method initSwagger = ssc.getClass().getDeclaredMethod("initSwagger"); |
| 142 | + swagger.set(swaggerCreator, new Swagger()); |
| 143 | + |
| 144 | + Method initSwagger = swaggerCreator.getClass().getDeclaredMethod("initSwagger"); |
259 | 145 | initSwagger.setAccessible(true); |
260 | | - initSwagger.invoke(ssc); |
261 | | - |
262 | | - // make the paths method accessible |
263 | | - Method addPaths = ssc.getClass().getDeclaredMethod("addPaths"); |
| 146 | + initSwagger.invoke(swaggerCreator); |
| 147 | + |
| 148 | + Method addPaths = swaggerCreator.getClass().getDeclaredMethod("addPaths"); |
264 | 149 | addPaths.setAccessible(true); |
265 | | - |
266 | | - addPaths.invoke(ssc); |
267 | | - } |
268 | | - |
269 | | - /** |
270 | | - * Some subresource appear to only support creation, not fetching or updating. References to the |
271 | | - * Get/Update definitions were still being included in the response options, despite not |
272 | | - * existing. Ensure that these references are not included in the resulting JSON to prevent |
273 | | - * swagger reference errors. See ticket: RESTWS-720 |
274 | | - */ |
275 | | - @Test |
276 | | - public void createOnlySubresourceDefinitions() { |
277 | | - SwaggerSpecificationCreator ssc = new SwaggerSpecificationCreator(); |
278 | | - String json = ssc.getJSON(); |
279 | | - |
280 | | - // A simple search will tell us if the problem definitions exist |
281 | | - assertFalse(json.contains("SystemsettingSubdetailsGet")); |
282 | | - assertFalse(json.contains("SystemsettingSubdetailsUpdate")); |
283 | | - assertTrue(json.contains("SystemsettingSubdetailsCreate")); |
| 150 | + addPaths.invoke(swaggerCreator); |
284 | 151 | } |
285 | 152 |
|
286 | 153 | /** |
287 | 154 | * Ensure that resources not directly related to the webservices.rest package are successfully |
288 | 155 | * defined in the swagger documentation. |
289 | 156 | */ |
290 | 157 | @Test |
291 | | - public void testUnrelatedResourceDefinitions() { |
292 | | - // ensure the statics are false first |
| 158 | + public void testUnrelatedResourceDefinitions_shouldBeDefined() { |
293 | 159 | UnrelatedGenericChildResource.getGETCalled = false; |
294 | 160 | UnrelatedGenericChildResource.getCREATECalled = false; |
295 | 161 | UnrelatedGenericChildResource.getUPDATECalled = false; |
296 | 162 |
|
297 | | - // make sure to reset the cache for multiple tests in the same run |
298 | 163 | if (SwaggerSpecificationCreator.isCached()) { |
299 | 164 | SwaggerSpecificationCreator.clearCache(); |
300 | 165 | } |
301 | 166 |
|
302 | | - SwaggerSpecificationCreator ssc = new SwaggerSpecificationCreator(); |
303 | | - ssc.getJSON(); |
| 167 | + swaggerCreator.getJSON(); |
304 | 168 |
|
305 | | - // check our custom methods were called |
306 | 169 | assertTrue(UnrelatedGenericChildResource.getGETCalled); |
307 | 170 | assertTrue(UnrelatedGenericChildResource.getCREATECalled); |
308 | 171 | assertTrue(UnrelatedGenericChildResource.getUPDATECalled); |
309 | 172 |
|
310 | | - // assert the definition is now in the swagger object |
311 | | - Swagger swagger = ssc.getSwagger(); |
| 173 | + Swagger swagger = swaggerCreator.getSwagger(); |
312 | 174 | assertTrue(swagger.getDefinitions().containsKey("UnrelatedGet")); |
313 | 175 | assertTrue(swagger.getDefinitions().containsKey("UnrelatedUpdate")); |
314 | 176 | assertTrue(swagger.getDefinitions().containsKey("UnrelatedCreate")); |
|
0 commit comments