From 9a6e431646f6b33bc1e683f2394b3651efeb61c4 Mon Sep 17 00:00:00 2001 From: Jon Ursenbach Date: Wed, 26 Jun 2019 11:14:58 -0700 Subject: [PATCH] Adding support for parameters that may have child `$ref` pointers. --- .../swagger-files/parameters-with-refs.json | 70 +++++++++++++++++++ example/swagger-files/types.json | 36 +++++++++- .../lib/parameters-to-json-schema.test.js | 53 ++++++++++++++ .../src/lib/parameters-to-json-schema.js | 10 ++- 4 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 example/swagger-files/parameters-with-refs.json diff --git a/example/swagger-files/parameters-with-refs.json b/example/swagger-files/parameters-with-refs.json new file mode 100644 index 000000000..4974d13f8 --- /dev/null +++ b/example/swagger-files/parameters-with-refs.json @@ -0,0 +1,70 @@ +{ + "openapi": "3.0.0", + "servers": [ + { + "url": "http://httpbin.org" + } + ], + "info": { + "version": "1.0.0", + "title": "An example of how we render $ref usage on resource parameters" + }, + "paths": { + "/anything": { + "get": { + "summary": "Query param with a child $ref", + "description": "", + "parameters": [ + { + "in": "query", + "name": "array (with a $ref)", + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/string_enum" + } + } + } + ], + "responses": {} + }, + "post": { + "summary": "Query param pointing to a $ref", + "description": "", + "parameters": [ + { + "$ref": "#/components/parameters/limitParam" + } + ], + "responses": {} + } + } + }, + "components": { + "parameters": { + "limitParam": { + "in": "query", + "name": "limit", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 20 + }, + "description": "The numbers of items to return." + } + }, + "schemas": { + "string_enum": { + "name": "string", + "enum": [ + "available", + "pending", + "sold" + ], + "type": "string" + } + } + } +} diff --git a/example/swagger-files/types.json b/example/swagger-files/types.json index 7da80b69d..8712553d9 100644 --- a/example/swagger-files/types.json +++ b/example/swagger-files/types.json @@ -59,13 +59,22 @@ "format": "string" }, "string (format: url)": { - "type": "string", - "format": "url" + "type": "string", + "format": "url" }, "string (format: unknown-format)": { "type": "string", "format": "unknown-format" }, + "string (enum)": { + "type": "string", + "enum": ["available", "pending", "sold"] + }, + "string (enum, with default)": { + "type": "string", + "enum": ["available", "pending", "sold"], + "default": "available" + }, "integer": { "type": "integer", "format": "int64", @@ -104,6 +113,18 @@ "boolean without description": { "type": "boolean" }, + "array (of strings)": { + "type": "array", + "items": { + "type": "string" + } + }, + "array (with a $ref)": { + "type": "array", + "items": { + "$ref": "#/components/schemas/string_enum" + } + }, "object": { "type": "object", "description": "This is an object with a description", @@ -400,6 +421,17 @@ "x-samples-enabled": true, "x-samples-languages": ["curl", "node", "ruby", "javascript", "python"], "components": { + "schemas": { + "string_enum": { + "name": "string", + "enum": [ + "available", + "pending", + "sold" + ], + "type": "string" + } + }, "requestBodies": { "Circular": { "type": "object", diff --git a/packages/api-explorer/__tests__/lib/parameters-to-json-schema.test.js b/packages/api-explorer/__tests__/lib/parameters-to-json-schema.test.js index 72f6f93c3..e0d2d204b 100644 --- a/packages/api-explorer/__tests__/lib/parameters-to-json-schema.test.js +++ b/packages/api-explorer/__tests__/lib/parameters-to-json-schema.test.js @@ -219,6 +219,25 @@ test('it should pass through type for non-body parameters', () => { ).toEqual('boolean'); }); +test('it should pass through type for non-body parameters that are arrays', () => { + expect( + parametersToJsonSchema({ + parameters: [ + { + in: 'query', + name: 'options', + schema: { + type: 'array', + items: { + type: 'string', + }, + }, + }, + ], + })[0].schema.properties.options.type, + ).toEqual('array'); +}); + test('it should pass through format', () => { expect( parametersToJsonSchema({ @@ -396,3 +415,37 @@ test('it should fetch $ref parameters', () => { )[0].schema.properties.param, ).toEqual(oas.components.parameters.Param.schema); }); + +test('it should fetch parameters that have a child $ref', () => { + const oas = { + components: { + schemas: { + string_enum: { + name: 'string', + enum: ['available', 'pending', 'sold'], + type: 'string', + }, + }, + }, + }; + + expect( + parametersToJsonSchema( + { + parameters: [ + { + in: 'query', + name: 'param', + schema: { + type: 'array', + items: { + $ref: '#/components/schemas/string_enum', + }, + }, + }, + ], + }, + oas, + )[0].schema.properties.param.items, + ).toEqual(oas.components.schemas.string_enum); +}); diff --git a/packages/api-explorer/src/lib/parameters-to-json-schema.js b/packages/api-explorer/src/lib/parameters-to-json-schema.js index 58356336a..929f919c3 100644 --- a/packages/api-explorer/src/lib/parameters-to-json-schema.js +++ b/packages/api-explorer/src/lib/parameters-to-json-schema.js @@ -47,7 +47,15 @@ function getOtherParams(pathOperation, oas) { if (current.schema) { if (current.schema.type === 'array') { schema.type = 'array'; - schema.items = current.schema.items; + + if ( + Object.keys(current.schema.items).length === 1 && + typeof current.schema.items.$ref !== 'undefined' + ) { + schema.items = findSchemaDefinition(current.schema.items.$ref, oas); + } else { + schema.items = current.schema.items; + } } if (typeof current.schema.default !== 'undefined') schema.default = current.schema.default;