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(); + }); + }); + }); }); });