Fix defintions replacing instead of merging

Fix defintions replacing instead of merging
This commit is contained in:
Luis Tejeda
2022-06-01 14:09:35 -05:00
parent 6fa20ccb48
commit d289dd0fdc
10 changed files with 214 additions and 14 deletions

View File

@@ -17,7 +17,8 @@ let path = require('path'),
pathBrowserify = require('path-browserify'),
BROWSER = 'browser',
{ DFS } = require('./dfs'),
deref = require('./deref.js');
deref = require('./deref.js'),
{ SWAGGER_VERSION } = require('./common/versionUtils');
/**
@@ -141,7 +142,7 @@ function getContentFromTrace(content, partial) {
* @returns {null} It modifies components global context
*/
function setValueInComponents(keyInComponents, components, value, version) {
const COMPONENTS_KEYS = version === '2.0' ? COMPONENTS_KEYS_20 : COMPONENTS_KEYS_30;
const COMPONENTS_KEYS = version === SWAGGER_VERSION ? COMPONENTS_KEYS_20 : COMPONENTS_KEYS_30;
let currentPlace = components,
target = keyInComponents[keyInComponents.length - 2],
key = keyInComponents.length === 2 && COMPONENTS_KEYS.includes(keyInComponents[0]) ?
@@ -372,6 +373,29 @@ function generateComponentsObject (documentContext, rootContent, refTypeResolver
});
}
/**
* Generates the components object wrapper
* @param {object} parsedOasObject The parsed root
* @param {string} version - The current version
* @returns {object} The components object wrapper
*/
function generateComponentsWrapper(parsedOasObject, version) {
let components = {};
if (version === SWAGGER_VERSION) {
COMPONENTS_KEYS_20.forEach((property) => {
if (parsedOasObject.hasOwnProperty(property)) {
components[property] = parsedOasObject[property];
}
});
}
else if (parsedOasObject.hasOwnProperty('components')) {
components = parsedOasObject.components;
}
return components;
}
module.exports = {
/**
* Takes in an spec root file and an array of data files
@@ -394,9 +418,7 @@ module.exports = {
rootContextData = algorithm.traverseAndBundle(specRoot, (currentNode) => {
return getNodeContentAndReferences(currentNode, allData, specRoot, version);
});
if (specRoot.parsed.oasObject.hasOwnProperty('components')) {
components = specRoot.parsed.oasObject.components;
}
components = generateComponentsWrapper(specRoot.parsed.oasObject, version);
generateComponentsObject(
rootContextData,
rootContextData.nodeContents[specRoot.fileName],

View File

@@ -4,6 +4,7 @@ const VERSION_30 = { key: 'openapi', version: '3.0' },
GENERIC_VERSION2 = { key: 'swagger', version: '2.' },
GENERIC_VERSION3 = { key: 'openapi', version: '3.' },
DEFAULT_SPEC_VERSION = VERSION_30.version,
SWAGGER_VERSION = VERSION_20.version,
fs = require('fs');
/**
@@ -257,5 +258,6 @@ module.exports = {
filterOptionsByVersion,
isSwagger,
compareVersion,
getVersionRegexBySpecificationVersion
getVersionRegexBySpecificationVersion,
SWAGGER_VERSION
};

View File

@@ -7,7 +7,9 @@ const { getKeyInComponents20 } = require('./swaggerUtils/componentParentMatcher'
escapedTilde = /~0/g,
jsonPointerLevelSeparator = '/',
escapedTildeString = '~0',
{ getKeyInComponents30 } = require('./30XUtils/componentsParentMatcher');
{ getKeyInComponents30 } = require('./30XUtils/componentsParentMatcher'),
{ SWAGGER_VERSION } = require('./common/versionUtils');
/**
* Encodes a filepath name so it can be a json pointer
@@ -39,7 +41,7 @@ function jsonPointerDecodeAndReplace(filePathName) {
*/
function getKeyInComponents(traceFromParent, filePathName, localPath, version) {
const localPart = localPath ? `${localPointer}${localPath}` : '',
is20 = version === '2.0';
is20 = version === SWAGGER_VERSION;
let result;
if (is20) {
@@ -76,7 +78,7 @@ function concatJsonPointer(encodeFunction, traceFromParent, targetInRoot) {
* @returns {string} - the concatenated json pointer
*/
function getJsonPointerRelationToRoot(encodeFunction, refValue, traceFromKey, version) {
let targetInRoot = version === '2.0' ? '' : '/components';
let targetInRoot = version === SWAGGER_VERSION ? '' : '/components';
if (refValue.startsWith(localPointer)) {
return refValue;
}

View File

@@ -6,7 +6,7 @@
const { ParseError } = require('./common/ParseError.js');
const { formatDataPath, checkIsCorrectType, isKnownType } = require('./common/schemaUtilsCommon.js'),
{ getConcreteSchemaUtils } = require('./common/versionUtils.js'),
{ getConcreteSchemaUtils, SWAGGER_VERSION } = require('./common/versionUtils.js'),
async = require('async'),
sdk = require('postman-collection'),
schemaFaker = require('../assets/json-schema-faker.js'),
@@ -4834,7 +4834,7 @@ module.exports = {
return bundleData;
});
let bundledFile = data[0].fileContent;
if (version === '2.0') {
if (version === SWAGGER_VERSION) {
Object.entries(data[0].components).forEach(([key, value]) => {
bundledFile[key] = value;
});
@@ -4870,7 +4870,7 @@ module.exports = {
let parsedContent = this.parseFileOrThrow(rootFile.content);
return { fileName: rootFile.fileName, content: rootFile.content, parsed: parsedContent };
}).filter((rootWithParsedContent) => {
let fileVersion = version === '2.0' ?
let fileVersion = version === SWAGGER_VERSION ?
rootWithParsedContent.parsed.oasObject.swagger :
rootWithParsedContent.parsed.oasObject.openapi;
bundleFormat = bundleFormat ? bundleFormat : rootWithParsedContent.parsed.inputFormat;

View File

@@ -1,7 +1,8 @@
const COMPONENTS_KEYS_20 = [
'definitions',
'parameters',
'responses'
'responses',
'securityDefinitions'
],
SCHEMA_PARENTS = [
'schema',

View File

@@ -0,0 +1,85 @@
{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore",
"description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"name": "Swagger API Team",
"email": "apiteam@swagger.io",
"url": "http://swagger.io"
},
"license": {
"name": "Apache 2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
}
},
"paths": {
"/pets": {
"get": {
"description": "Returns all pets",
"content": {
"application/json": {
"schema": {
"$ref": "#/definitions/~1paths~1path.yaml%23~1definitions~1Error"
}
},
"description": "Returns all pets from the system that the user has access to,",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "A list of pets.,",
"schema": {
"$ref": "#/definitions/~1paths~1path.yaml%23~1definitions~1Pet"
}
}
}
}
}
}
},
"definitions": {
"Pet": {
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
},
"Error": {
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
},
"/paths/path.yaml#/definitions/Error": {
"$ref": "#/definitions/Error"
},
"/paths/path.yaml#/definitions/Pet": {
"$ref": "#/definitions/Pet"
}
}
}

View File

@@ -0,0 +1,13 @@
description: Returns all pets
content:
application/json:
schema:
$ref: "#/definitions/Error"
description: Returns all pets from the system that the user has access to,
produces:
- application/json
responses:
200:
description: A list of pets.,
schema:
$ref: "#/definitions/Pet"

View File

@@ -0,0 +1,3 @@
/pets:
get:
"$ref": "./path.yaml"

View File

@@ -0,0 +1,38 @@
swagger: '2.0'
info:
version: 1.0.0
title: Swagger Petstore
description: A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification
termsOfService: http://swagger.io/terms/
contact:
name: Swagger API Team
email: apiteam@swagger.io
url: http://swagger.io
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
paths:
"$ref": "./paths/paths.yaml"
definitions:
Pet:
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
Error:
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string

View File

@@ -28,7 +28,8 @@ let expect = require('chai').expect,
refTags20 = path.join(__dirname, SWAGGER_MULTIFILE_FOLDER + '/referenced_tags'),
basicExample = path.join(__dirname, SWAGGER_MULTIFILE_FOLDER + '/basicExample'),
simpleRef = path.join(__dirname, SWAGGER_MULTIFILE_FOLDER + '/simpleRef'),
refPaths20 = path.join(__dirname, SWAGGER_MULTIFILE_FOLDER + '/referenced_paths');
refPaths20 = path.join(__dirname, SWAGGER_MULTIFILE_FOLDER + '/referenced_paths'),
refPathsRefToLocalSchema20 = path.join(__dirname, SWAGGER_MULTIFILE_FOLDER + '/referenced_paths_local_schema');
describe('bundle files method - 3.0', function () {
it('Should return bundled file as json - schema_from_response', async function () {
@@ -913,6 +914,39 @@ describe('bundle files method - 2.0', function () {
expect(res.result).to.be.true;
expect(res.output.data.bundledContent).to.be.equal(expected);
});
it('Should return bundled file with referenced paths from root - path references local schema', async function () {
let contentRootFile = fs.readFileSync(refPathsRefToLocalSchema20 + '/root.yaml', 'utf8'),
paths = fs.readFileSync(refPathsRefToLocalSchema20 + '/paths/paths.yaml', 'utf8'),
path = fs.readFileSync(refPathsRefToLocalSchema20 + '/paths/path.yaml', 'utf8'),
expected = fs.readFileSync(refPathsRefToLocalSchema20 + '/expected.json', 'utf8'),
input = {
type: 'folder',
specificationVersion: '2.0',
rootFiles: [
{
path: '/root.yaml',
content: contentRootFile
}
],
data: [
{
path: '/paths/paths.yaml',
content: paths
},
{
path: '/paths/path.yaml',
content: path
}
],
options: {},
bundleFormat: 'JSON'
};
const res = await Converter.bundle(input);
expect(res).to.not.be.empty;
expect(res.result).to.be.true;
expect(res.output.data.bundledContent).to.be.equal(expected);
});
});
describe('getReferences method when node does not have any reference', function() {