From 9d6b730cdac711651984df095a2ab6cc155f24bd Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Tue, 10 Jan 2023 14:54:27 +0100 Subject: [PATCH] test(resolver): add tests for OpenAPI 3.1 spec obj resolution Spec object can be provided instead of URL. If baseDoc or url options are not provided, default retrival URL is set to http://smartbear.com Refs #2754 --- src/resolver/strategies/openapi-3-1.js | 3 +- .../openapi-3-1/__snapshots__/index.js.snap | 916 +++++++++++++++++- test/resolver/strategies/openapi-3-1/index.js | 51 +- 3 files changed, 956 insertions(+), 14 deletions(-) diff --git a/src/resolver/strategies/openapi-3-1.js b/src/resolver/strategies/openapi-3-1.js index 723b298dc..44fd57deb 100644 --- a/src/resolver/strategies/openapi-3-1.js +++ b/src/resolver/strategies/openapi-3-1.js @@ -25,10 +25,11 @@ const resolveOpenAPI31Strategy = async (options) => { useCircularStructures = false, skipNormalization = false, } = options; + const defaultRetrievalURL = 'https://smartbear.com/'; const openApiElement = OpenApi3_1Element.refract(spec); const dereferenced = await dereferenceApiDOM(openApiElement, { resolve: { - baseURI: optionsUtil.retrievalURI(options), + baseURI: optionsUtil.retrievalURI(options) || defaultRetrievalURL, resolvers: [ HttpResolverSwaggerClient({ timeout: timeout || 10000, diff --git a/test/resolver/strategies/openapi-3-1/__snapshots__/index.js.snap b/test/resolver/strategies/openapi-3-1/__snapshots__/index.js.snap index 0d9b77e9a..ce074c301 100644 --- a/test/resolver/strategies/openapi-3-1/__snapshots__/index.js.snap +++ b/test/resolver/strategies/openapi-3-1/__snapshots__/index.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition and allowMetaPatches=true should resolve 1`] = ` +exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via URL and allowMetaPatches=true should resolve 1`] = ` { "errors": [], "spec": { @@ -309,7 +309,7 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition and allow } `; -exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition and allowMetaPatches=true should resolve 2`] = ` +exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via URL and allowMetaPatches=true should resolve 2`] = ` { "errors": [], "spec": { @@ -611,7 +611,7 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition and allow } `; -exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition and useCircularStructures=false should resolve 1`] = ` +exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via URL and useCircularStructures=false should resolve 1`] = ` { "errors": [], "spec": { @@ -646,7 +646,7 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition and useCi } `; -exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition and useCircularStructures=true should resolve 1`] = ` +exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via URL and useCircularStructures=true should resolve 1`] = ` { "errors": [], "spec": { @@ -688,7 +688,913 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition and useCi } `; -exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition should resolve 1`] = ` +exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via URL should resolve 1`] = ` +{ + "errors": [], + "spec": { + "$$normalized": true, + "components": { + "schemas": { + "Error": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "required": [ + "code", + "message", + ], + "type": "object", + }, + "Pet": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + "type": "object", + }, + "Pets": { + "items": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + "type": "object", + }, + "maxItems": 100, + "type": "array", + }, + }, + }, + "info": { + "license": { + "name": "MIT", + }, + "title": "Swagger Petstore", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": { + "/pets": { + "get": { + "operationId": "listPets", + "parameters": [ + { + "description": "How many items to return at one time (max 100)", + "in": "query", + "name": "limit", + "required": false, + "schema": { + "format": "int32", + "maximum": 100, + "type": "integer", + }, + }, + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + "type": "object", + }, + "maxItems": 100, + "type": "array", + }, + }, + }, + "description": "A paged array of pets", + "headers": { + "x-next": { + "description": "A link to the next page of responses", + "schema": { + "type": "string", + }, + }, + }, + }, + "default": { + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "required": [ + "code", + "message", + ], + "type": "object", + }, + }, + }, + "description": "unexpected error", + }, + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + "summary": "List all pets", + "tags": [ + "pets", + ], + }, + "post": { + "operationId": "createPets", + "responses": { + "201": { + "description": "Null response", + }, + "default": { + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "required": [ + "code", + "message", + ], + "type": "object", + }, + }, + }, + "description": "unexpected error", + }, + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + "summary": "Create a pet", + "tags": [ + "pets", + ], + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + }, + "/pets/{petId}": { + "get": { + "operationId": "showPetById", + "parameters": [ + { + "description": "The id of the pet to retrieve", + "in": "path", + "name": "petId", + "required": true, + "schema": { + "type": "string", + }, + }, + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + "type": "object", + }, + }, + }, + "description": "Expected response to a valid request", + }, + "default": { + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "required": [ + "code", + "message", + ], + "type": "object", + }, + }, + }, + "description": "unexpected error", + }, + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + "summary": "Info for a specific pet", + "tags": [ + "pets", + ], + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + }, + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + }, +} +`; + +exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec option and baseDoc option is provided should resolve 1`] = ` +{ + "errors": [], + "spec": { + "$$normalized": true, + "components": { + "schemas": { + "Error": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "required": [ + "code", + "message", + ], + "type": "object", + }, + "Pet": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + "type": "object", + }, + "Pets": { + "items": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + "type": "object", + }, + "maxItems": 100, + "type": "array", + }, + }, + }, + "info": { + "license": { + "name": "MIT", + }, + "title": "Swagger Petstore", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": { + "/pets": { + "get": { + "operationId": "listPets", + "parameters": [ + { + "description": "How many items to return at one time (max 100)", + "in": "query", + "name": "limit", + "required": false, + "schema": { + "format": "int32", + "maximum": 100, + "type": "integer", + }, + }, + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + "type": "object", + }, + "maxItems": 100, + "type": "array", + }, + }, + }, + "description": "A paged array of pets", + "headers": { + "x-next": { + "description": "A link to the next page of responses", + "schema": { + "type": "string", + }, + }, + }, + }, + "default": { + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "required": [ + "code", + "message", + ], + "type": "object", + }, + }, + }, + "description": "unexpected error", + }, + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + "summary": "List all pets", + "tags": [ + "pets", + ], + }, + "post": { + "operationId": "createPets", + "responses": { + "201": { + "description": "Null response", + }, + "default": { + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "required": [ + "code", + "message", + ], + "type": "object", + }, + }, + }, + "description": "unexpected error", + }, + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + "summary": "Create a pet", + "tags": [ + "pets", + ], + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + }, + "/pets/{petId}": { + "get": { + "operationId": "showPetById", + "parameters": [ + { + "description": "The id of the pet to retrieve", + "in": "path", + "name": "petId", + "required": true, + "schema": { + "type": "string", + }, + }, + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + "type": "object", + }, + }, + }, + "description": "Expected response to a valid request", + }, + "default": { + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "required": [ + "code", + "message", + ], + "type": "object", + }, + }, + }, + "description": "unexpected error", + }, + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + "summary": "Info for a specific pet", + "tags": [ + "pets", + ], + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + }, + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + }, +} +`; + +exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec option and neither baseDoc nor url option is provided should resolve 1`] = ` +{ + "errors": [], + "spec": { + "$$normalized": true, + "components": { + "schemas": { + "Error": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "required": [ + "code", + "message", + ], + "type": "object", + }, + "Pet": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + "type": "object", + }, + "Pets": { + "items": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + "type": "object", + }, + "maxItems": 100, + "type": "array", + }, + }, + }, + "info": { + "license": { + "name": "MIT", + }, + "title": "Swagger Petstore", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": { + "/pets": { + "get": { + "operationId": "listPets", + "parameters": [ + { + "description": "How many items to return at one time (max 100)", + "in": "query", + "name": "limit", + "required": false, + "schema": { + "format": "int32", + "maximum": 100, + "type": "integer", + }, + }, + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + "type": "object", + }, + "maxItems": 100, + "type": "array", + }, + }, + }, + "description": "A paged array of pets", + "headers": { + "x-next": { + "description": "A link to the next page of responses", + "schema": { + "type": "string", + }, + }, + }, + }, + "default": { + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "required": [ + "code", + "message", + ], + "type": "object", + }, + }, + }, + "description": "unexpected error", + }, + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + "summary": "List all pets", + "tags": [ + "pets", + ], + }, + "post": { + "operationId": "createPets", + "responses": { + "201": { + "description": "Null response", + }, + "default": { + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "required": [ + "code", + "message", + ], + "type": "object", + }, + }, + }, + "description": "unexpected error", + }, + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + "summary": "Create a pet", + "tags": [ + "pets", + ], + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + }, + "/pets/{petId}": { + "get": { + "operationId": "showPetById", + "parameters": [ + { + "description": "The id of the pet to retrieve", + "in": "path", + "name": "petId", + "required": true, + "schema": { + "type": "string", + }, + }, + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + "type": "object", + }, + }, + }, + "description": "Expected response to a valid request", + }, + "default": { + "content": { + "application/json": { + "schema": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "required": [ + "code", + "message", + ], + "type": "object", + }, + }, + }, + "description": "unexpected error", + }, + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + "summary": "Info for a specific pet", + "tags": [ + "pets", + ], + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + }, + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1", + }, + ], + }, +} +`; + +exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec option and url option is provided should resolve 1`] = ` { "errors": [], "spec": { diff --git a/test/resolver/strategies/openapi-3-1/index.js b/test/resolver/strategies/openapi-3-1/index.js index 0a7ad60c3..d1df465aa 100644 --- a/test/resolver/strategies/openapi-3-1/index.js +++ b/test/resolver/strategies/openapi-3-1/index.js @@ -1,22 +1,22 @@ import path from 'node:path'; import fetchMock from 'fetch-mock'; -import Swagger from '../../../../src/index.js'; +import SwaggerClient from '../../../../src/index.js'; const fixturePath = path.join(__dirname, '__fixtures__'); describe('resolve', () => { describe('OpenAPI 3.1.0 strategy', () => { test('should expose a resolver function', () => { - expect(Swagger.resolve).toBeInstanceOf(Function); + expect(SwaggerClient.resolve).toBeInstanceOf(Function); }); - describe('given OpenAPI 3.1.0 definition', () => { + describe('given OpenAPI 3.1.0 definition via URL', () => { test('should resolve', async () => { const url = 'https://example.com/petstore.json'; const response = new Response(globalThis.loadFile(path.join(fixturePath, 'petstore.json'))); fetchMock.get(url, response, { repeat: 1 }); - const resolvedSpec = await Swagger.resolve({ + const resolvedSpec = await SwaggerClient.resolve({ url: 'https://example.com/petstore.json', allowMetaPatches: false, }); @@ -33,7 +33,7 @@ describe('resolve', () => { globalThis.loadFile(path.join(fixturePath, 'petstore.json')) ); fetchMock.get(url, response, { repeat: 1 }); - const resolvedSpec = await Swagger.resolve({ + const resolvedSpec = await SwaggerClient.resolve({ url: 'https://example.com/petstore.json', allowMetaPatches: true, }); @@ -51,7 +51,7 @@ describe('resolve', () => { globalThis.loadFile(path.join(fixturePath, 'petstore.json')) ); fetchMock.get(url, response, { repeat: 1 }); - const resolvedSpec = await Swagger.resolve({ + const resolvedSpec = await SwaggerClient.resolve({ url: 'https://example.com/petstore.json', allowMetaPatches: false, }); @@ -69,7 +69,7 @@ describe('resolve', () => { globalThis.loadFile(path.join(fixturePath, 'circular-structures.json')) ); fetchMock.get(url, response, { repeat: 1 }); - const resolvedSpec = await Swagger.resolve({ + const resolvedSpec = await SwaggerClient.resolve({ url: 'https://example.com/circular-structures.json', useCircularStructures: true, }); @@ -87,7 +87,7 @@ describe('resolve', () => { globalThis.loadFile(path.join(fixturePath, 'circular-structures.json')) ); fetchMock.get(url, response, { repeat: 1 }); - const resolvedSpec = await Swagger.resolve({ + const resolvedSpec = await SwaggerClient.resolve({ url: 'https://example.com/circular-structures.json', useCircularStructures: false, }); @@ -98,5 +98,40 @@ describe('resolve', () => { }); }); }); + + describe('given OpenAPI 3.1.0 definition via spec option', () => { + describe('and neither baseDoc nor url option is provided', () => { + test('should resolve', async () => { + const spec = globalThis.loadJsonFile(path.join(fixturePath, 'petstore.json')); + const resolvedSpec = await SwaggerClient.resolve({ spec }); + + expect(resolvedSpec).toMatchSnapshot(); + }); + }); + + describe('and baseDoc option is provided', () => { + test('should resolve', async () => { + const spec = globalThis.loadJsonFile(path.join(fixturePath, 'petstore.json')); + const resolvedSpec = await SwaggerClient.resolve({ + spec, + baseDoc: 'https://example.com/', + }); + + expect(resolvedSpec).toMatchSnapshot(); + }); + }); + + describe('and url option is provided', () => { + test('should resolve', async () => { + const spec = globalThis.loadJsonFile(path.join(fixturePath, 'petstore.json')); + const resolvedSpec = await SwaggerClient.resolve({ + spec, + url: 'https://example.com/', + }); + + expect(resolvedSpec).toMatchSnapshot(); + }); + }); + }); }); });