From 32e156fca7ab20dac993e790927302f804d8eef5 Mon Sep 17 00:00:00 2001 From: Daniel Kenyon-Jones Date: Tue, 5 Sep 2023 15:34:08 +0100 Subject: [PATCH] feat!: generate models for OpenAPI parameters (#1498) Co-authored-by: Daniel Kenyon-Jones --- src/processors/OpenAPIInputProcessor.ts | 33 ++++++++++++ test/processors/OpenAPIInputProcessor.spec.ts | 54 ++++++++++++++++--- .../OpenAPIInputProcessor/basic.json | 11 ++++ .../OpenAPIInputProcessor.spec.ts.snap | 24 +++++++++ 4 files changed, 116 insertions(+), 6 deletions(-) diff --git a/src/processors/OpenAPIInputProcessor.ts b/src/processors/OpenAPIInputProcessor.ts index bd05e36fac..88e175a635 100644 --- a/src/processors/OpenAPIInputProcessor.ts +++ b/src/processors/OpenAPIInputProcessor.ts @@ -101,6 +101,12 @@ export class OpenAPIInputProcessor extends AbstractInputProcessor { inputModel, options ); + this.iterateParameters( + pathObject.parameters, + `${formattedPathName}_parameters`, + inputModel, + options + ); } } @@ -112,6 +118,12 @@ export class OpenAPIInputProcessor extends AbstractInputProcessor { ) { if (operation) { this.iterateResponses(operation.responses, path, inputModel, options); + this.iterateParameters( + operation.parameters, + `${path}_parameters`, + inputModel, + options + ); if (operation.requestBody) { this.iterateMediaType( @@ -160,6 +172,27 @@ export class OpenAPIInputProcessor extends AbstractInputProcessor { } } + private iterateParameters( + parameters: + | (OpenAPIV3.ReferenceObject | OpenAPIV3.ParameterObject)[] + | undefined, + path: string, + inputModel: InputMetaModel, + options?: ProcessorOptions + ) { + for (const parameterObject of parameters || []) { + const parameter = parameterObject as OpenAPIV3.ParameterObject; + if (parameter.schema) { + this.includeSchema( + parameter.schema as OpenAPIV3.SchemaObject, + `${path}_${parameter.in}_${parameter.name}`, + inputModel, + options + ); + } + } + } + private iterateMediaType( mediaTypes: { [media: string]: OpenAPIV3.MediaTypeObject }, path: string, diff --git a/test/processors/OpenAPIInputProcessor.spec.ts b/test/processors/OpenAPIInputProcessor.spec.ts index 3b1cf5afdb..8a31d7f3f5 100644 --- a/test/processors/OpenAPIInputProcessor.spec.ts +++ b/test/processors/OpenAPIInputProcessor.spec.ts @@ -9,7 +9,10 @@ const basicDoc = JSON.parse( ) ); jest.mock('../../src/utils/LoggingInterface'); -jest.spyOn(OpenAPIInputProcessor, 'convertToInternalSchema'); +const processorSpy = jest.spyOn( + OpenAPIInputProcessor, + 'convertToInternalSchema' +); const mockedReturnModels = [new CommonModel()]; const mockedMetaModel = new AnyModel('', undefined); jest.mock('../../src/helpers/CommonModelToMetaModel', () => { @@ -34,6 +37,9 @@ describe('OpenAPIInputProcessor', () => { afterAll(() => { jest.restoreAllMocks(); }); + afterEach(() => { + jest.clearAllMocks(); + }); describe('shouldProcess()', () => { const processor = new OpenAPIInputProcessor(); test('should be able to process OpenAPI 3.0.0 documents', () => { @@ -82,11 +88,47 @@ describe('OpenAPIInputProcessor', () => { const processor = new OpenAPIInputProcessor(); const commonInputModel = await processor.process(basicDoc); expect(commonInputModel).toMatchSnapshot(); - expect( - ( - OpenAPIInputProcessor.convertToInternalSchema as any as jest.SpyInstance - ).mock.calls - ).toMatchSnapshot(); + expect(processorSpy.mock.calls).toMatchSnapshot(); + }); + test('should include schema for parameters', async () => { + const doc = { + openapi: '3.0.3', + info: {}, + paths: { + '/test': { + parameters: [ + { + name: 'path_parameter', + in: 'header', + schema: { type: 'string' } + } + ], + get: { + parameters: [ + { + name: 'operation_parameter', + in: 'query', + schema: { type: 'string' } + } + ], + responses: { + 204: {} + } + } + } + } + }; + + const processor = new OpenAPIInputProcessor(); + await processor.process(doc); + expect(processorSpy.mock.calls).toContainEqual([ + { type: 'string' }, + 'test_get_parameters_query_operation_parameter' + ]); + expect(processorSpy.mock.calls).toContainEqual([ + { type: 'string' }, + 'test_parameters_header_path_parameter' + ]); }); }); }); diff --git a/test/processors/OpenAPIInputProcessor/basic.json b/test/processors/OpenAPIInputProcessor/basic.json index fb02cec8df..597df89552 100644 --- a/test/processors/OpenAPIInputProcessor/basic.json +++ b/test/processors/OpenAPIInputProcessor/basic.json @@ -5,6 +5,17 @@ }, "paths": { "/test": { + "parameters": [ + { + "name": "Authorization", + "in": "header", + "required": true, + "description": "credentials that authenticate a user agent with a server", + "schema": { + "type": "string" + } + } + ], "post": { "parameters": [ { diff --git a/test/processors/__snapshots__/OpenAPIInputProcessor.spec.ts.snap b/test/processors/__snapshots__/OpenAPIInputProcessor.spec.ts.snap index fc09e3799b..8891c89b8c 100644 --- a/test/processors/__snapshots__/OpenAPIInputProcessor.spec.ts.snap +++ b/test/processors/__snapshots__/OpenAPIInputProcessor.spec.ts.snap @@ -197,6 +197,17 @@ InputMetaModel { }, }, }, + "parameters": Array [ + Object { + "description": "credentials that authenticate a user agent with a server", + "in": "header", + "name": "Authorization", + "required": true, + "schema": Object { + "type": "string", + }, + }, + ], "patch": Object { "requestBody": Object { "content": Object { @@ -552,6 +563,13 @@ Array [ }, "test_post_200_application_json", ], + Array [ + Object { + "format": "uri", + "type": "string", + }, + "test_post_parameters_query_callbackUrl", + ], Array [ Object { "properties": Object { @@ -768,5 +786,11 @@ Array [ }, "test_trace_application_json", ], + Array [ + Object { + "type": "string", + }, + "test_parameters_header_Authorization", + ], ] `;