|
1 | 1 | import { z, ZodSchema } from 'zod'; |
2 | 2 | import { OperationObject, PathItemObject } from 'openapi3-ts'; |
3 | | -import { |
4 | | - OpenAPIGenerator, |
5 | | - OpenAPIObjectConfig, |
6 | | -} from '../src/openapi-generator'; |
7 | | -import { OpenAPIRegistry, RouteConfig } from '../src/openapi-registry'; |
8 | | -import { registerSchema } from './lib/helpers'; |
9 | | - |
10 | | -function createTestRoute(props: Partial<RouteConfig> = {}): RouteConfig { |
11 | | - return { |
12 | | - method: 'get', |
13 | | - path: '/', |
14 | | - responses: { |
15 | | - 200: { |
16 | | - description: 'OK Response', |
17 | | - }, |
18 | | - }, |
19 | | - ...props, |
20 | | - }; |
21 | | -} |
22 | | - |
23 | | -const testDocConfig: OpenAPIObjectConfig = { |
24 | | - info: { |
25 | | - version: '1.0.0', |
26 | | - title: 'Swagger Petstore', |
27 | | - description: 'A sample API', |
28 | | - termsOfService: 'http://swagger.io/terms/', |
29 | | - license: { |
30 | | - name: 'Apache 2.0', |
31 | | - url: 'https://www.apache.org/licenses/LICENSE-2.0.html', |
32 | | - }, |
33 | | - }, |
34 | | - servers: [{ url: 'v1' }], |
35 | | -}; |
| 3 | +import { OpenAPIGenerator } from '../../src/openapi-generator'; |
| 4 | +import { OpenAPIRegistry, RouteConfig } from '../../src/openapi-registry'; |
| 5 | +import { createTestRoute, registerSchema, testDocConfig } from '../lib/helpers'; |
36 | 6 |
|
37 | 7 | const routeTests = ({ |
38 | 8 | registerFunction, |
@@ -190,244 +160,6 @@ const routeTests = ({ |
190 | 160 | }); |
191 | 161 | }); |
192 | 162 |
|
193 | | - describe('parameters', () => { |
194 | | - it('generates a query parameter for route', () => { |
195 | | - const routeParameters = generateParamsForRoute({ |
196 | | - request: { query: z.object({ test: z.string() }) }, |
197 | | - }); |
198 | | - |
199 | | - expect(routeParameters).toEqual([ |
200 | | - { |
201 | | - in: 'query', |
202 | | - name: 'test', |
203 | | - required: true, |
204 | | - schema: { |
205 | | - type: 'string', |
206 | | - }, |
207 | | - }, |
208 | | - ]); |
209 | | - }); |
210 | | - |
211 | | - it('generates a path parameter for route', () => { |
212 | | - const routeParameters = generateParamsForRoute({ |
213 | | - request: { params: z.object({ test: z.string() }) }, |
214 | | - }); |
215 | | - |
216 | | - expect(routeParameters).toEqual([ |
217 | | - { |
218 | | - in: 'path', |
219 | | - name: 'test', |
220 | | - required: true, |
221 | | - schema: { |
222 | | - type: 'string', |
223 | | - }, |
224 | | - }, |
225 | | - ]); |
226 | | - }); |
227 | | - |
228 | | - it('generates a header parameter for route', () => { |
229 | | - const routeParameters = generateParamsForRoute({ |
230 | | - request: { |
231 | | - headers: [z.string().openapi({ param: { name: 'test' } })], |
232 | | - }, |
233 | | - }); |
234 | | - |
235 | | - expect(routeParameters).toEqual([ |
236 | | - { |
237 | | - in: 'header', |
238 | | - name: 'test', |
239 | | - required: true, |
240 | | - schema: { |
241 | | - type: 'string', |
242 | | - }, |
243 | | - }, |
244 | | - ]); |
245 | | - }); |
246 | | - |
247 | | - it('generates a reference header parameter for route', () => { |
248 | | - const TestHeader = registerSchema('TestHeader', z.string()).openapi({ |
249 | | - param: { name: 'test', in: 'header' }, |
250 | | - }); |
251 | | - |
252 | | - const routeParameters = generateParamsForRoute( |
253 | | - { |
254 | | - request: { headers: [TestHeader] }, |
255 | | - }, |
256 | | - [TestHeader] |
257 | | - ); |
258 | | - |
259 | | - expect(routeParameters).toEqual([ |
260 | | - { |
261 | | - $ref: '#/components/parameters/TestHeader', |
262 | | - }, |
263 | | - ]); |
264 | | - }); |
265 | | - |
266 | | - it('generates a reference query parameter for route', () => { |
267 | | - const TestQuery = registerSchema('TestQuery', z.string()).openapi({ |
268 | | - param: { name: 'test', in: 'query' }, |
269 | | - }); |
270 | | - |
271 | | - const routeParameters = generateParamsForRoute( |
272 | | - { |
273 | | - request: { query: z.object({ test: TestQuery }) }, |
274 | | - }, |
275 | | - [TestQuery] |
276 | | - ); |
277 | | - |
278 | | - expect(routeParameters).toEqual([ |
279 | | - { |
280 | | - $ref: '#/components/parameters/TestQuery', |
281 | | - }, |
282 | | - ]); |
283 | | - }); |
284 | | - |
285 | | - it('generates required based on inner schema', () => { |
286 | | - const routeParameters = generateParamsForRoute({ |
287 | | - request: { |
288 | | - query: z.object({ test: z.string().optional().default('test') }), |
289 | | - }, |
290 | | - }); |
291 | | - |
292 | | - expect(routeParameters).toEqual([ |
293 | | - { |
294 | | - in: 'query', |
295 | | - name: 'test', |
296 | | - required: false, |
297 | | - schema: { |
298 | | - type: 'string', |
299 | | - default: 'test', |
300 | | - }, |
301 | | - }, |
302 | | - ]); |
303 | | - }); |
304 | | - |
305 | | - it('supports strict zod objects', () => { |
306 | | - const routeParameters = generateParamsForRoute({ |
307 | | - request: { |
308 | | - query: z.strictObject({ |
309 | | - test: z.string().optional().default('test'), |
310 | | - }), |
311 | | - }, |
312 | | - }); |
313 | | - |
314 | | - expect(routeParameters).toEqual([ |
315 | | - { |
316 | | - in: 'query', |
317 | | - name: 'test', |
318 | | - required: false, |
319 | | - schema: { |
320 | | - type: 'string', |
321 | | - default: 'test', |
322 | | - }, |
323 | | - }, |
324 | | - ]); |
325 | | - }); |
326 | | - |
327 | | - describe('errors', () => { |
328 | | - it('throws an error in case of names mismatch', () => { |
329 | | - expect(() => |
330 | | - generateParamsForRoute({ |
331 | | - request: { |
332 | | - query: z.object({ |
333 | | - test: z.string().openapi({ param: { name: 'another' } }), |
334 | | - }), |
335 | | - }, |
336 | | - }) |
337 | | - ).toThrowError(/^Conflicting name/); |
338 | | - }); |
339 | | - |
340 | | - it('throws an error in case of location mismatch', () => { |
341 | | - expect(() => |
342 | | - generateParamsForRoute({ |
343 | | - request: { |
344 | | - query: z.object({ |
345 | | - test: z.string().openapi({ param: { in: 'header' } }), |
346 | | - }), |
347 | | - }, |
348 | | - }) |
349 | | - ).toThrowError(/^Conflicting location/); |
350 | | - }); |
351 | | - |
352 | | - it('throws an error in case of location mismatch with reference', () => { |
353 | | - const TestHeader = registerSchema('TestHeader', z.string()).openapi({ |
354 | | - param: { name: 'test', in: 'header' }, |
355 | | - }); |
356 | | - |
357 | | - expect(() => |
358 | | - generateParamsForRoute( |
359 | | - { |
360 | | - request: { query: z.object({ test: TestHeader }) }, |
361 | | - }, |
362 | | - [TestHeader] |
363 | | - ) |
364 | | - ).toThrowError(/^Conflicting location/); |
365 | | - }); |
366 | | - |
367 | | - it('throws an error in case of name mismatch with reference', () => { |
368 | | - const TestQuery = registerSchema('TestQuery', z.string()).openapi({ |
369 | | - param: { name: 'test', in: 'query' }, |
370 | | - }); |
371 | | - |
372 | | - expect(() => |
373 | | - generateParamsForRoute( |
374 | | - { |
375 | | - request: { query: z.object({ randomName: TestQuery }) }, |
376 | | - }, |
377 | | - [TestQuery] |
378 | | - ) |
379 | | - ).toThrowError(/^Conflicting name/); |
380 | | - }); |
381 | | - |
382 | | - it('throws an error in case of missing name', () => { |
383 | | - expect(() => |
384 | | - generateParamsForRoute({ |
385 | | - request: { headers: [z.string()] }, |
386 | | - }) |
387 | | - ).toThrowError(/^Missing parameter data, please specify `name`/); |
388 | | - }); |
389 | | - |
390 | | - it('throws an error in case of missing location when registering a parameter', () => { |
391 | | - const TestQuery = registerSchema('TestQuery', z.string()).openapi({ |
392 | | - param: { name: 'test' }, |
393 | | - }); |
394 | | - |
395 | | - expect(() => generateParamsForRoute({}, [TestQuery])).toThrowError( |
396 | | - /^Missing parameter data, please specify `in`/ |
397 | | - ); |
398 | | - }); |
399 | | - }); |
400 | | - |
401 | | - function generateParamsForRoute( |
402 | | - props: Partial<RouteConfig> = {}, |
403 | | - paramsToRegister?: ZodSchema<any>[] |
404 | | - ): OperationObject['parameters'] { |
405 | | - const route = createTestRoute(props); |
406 | | - |
407 | | - const paramDefinitions = |
408 | | - paramsToRegister?.map(schema => ({ |
409 | | - type: 'parameter' as const, |
410 | | - schema, |
411 | | - })) ?? []; |
412 | | - |
413 | | - const routeDefinition = { |
414 | | - type: 'route' as const, |
415 | | - route, |
416 | | - }; |
417 | | - |
418 | | - const { paths } = new OpenAPIGenerator( |
419 | | - [...paramDefinitions, routeDefinition], |
420 | | - '3.0.0' |
421 | | - ).generateDocument(testDocConfig); |
422 | | - |
423 | | - const routes = paths[route.path] as PathItemObject; |
424 | | - |
425 | | - const routeDoc = routes[route.method]; |
426 | | - |
427 | | - return routeDoc?.parameters; |
428 | | - } |
429 | | - }); |
430 | | - |
431 | 163 | describe('request body', () => { |
432 | 164 | it('can specify request body metadata - description/required', () => { |
433 | 165 | const registry = new OpenAPIRegistry(); |
|
0 commit comments