mirror of
https://github.com/postmanlabs/openapi-to-postman.git
synced 2022-11-29 22:05:00 +03:00
Merge branch 'develop' into fix496/validateWithServers
This commit is contained in:
14
.npmignore
14
.npmignore
@@ -43,4 +43,16 @@ test/data/.temp
|
|||||||
|
|
||||||
# Prevent unit test coverage reports from being added
|
# Prevent unit test coverage reports from being added
|
||||||
.coverage
|
.coverage
|
||||||
.nyc_output
|
.nyc_output
|
||||||
|
|
||||||
|
# - Prevent config and test files from being added
|
||||||
|
.git*
|
||||||
|
.github/
|
||||||
|
scripts/
|
||||||
|
test/
|
||||||
|
examples/
|
||||||
|
.eslintrc
|
||||||
|
.eslintignore
|
||||||
|
.nycrc
|
||||||
|
.editorconfig
|
||||||
|
.jsdoc-config.json
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
# OpenAPI-Postman Changelog
|
# OpenAPI-Postman Changelog
|
||||||
|
|
||||||
|
#### v4.0.0 (July 12, 2022)
|
||||||
|
* Added support for new multi-file API detectRootFiles() for OpenAPI 3 and Swagger 2 formats to support detection of root files among multiple files.
|
||||||
|
* Added support for new multi-file API detectRelatedFiles() for OpenAPI 3 and Swagger 2 formats to support detection of related files for a provided root file amongst multiple files.
|
||||||
|
* Added support for new multi-file API bundle() for OpenAPI 3 and Swagger 2 formats to support bundling of root files from provided multiple files.
|
||||||
|
|
||||||
#### v3.2.0 (May 02, 2022)
|
#### v3.2.0 (May 02, 2022)
|
||||||
* Fixed some of critical and high level severity vulnerabilities.
|
* Fixed some of critical and high level severity vulnerabilities.
|
||||||
* Fixed issue [#10752](https://github.com/postmanlabs/postman-app-support/issues/10752) where deepObject style parameters were not generated correctly.
|
* Fixed issue [#10752](https://github.com/postmanlabs/postman-app-support/issues/10752) where deepObject style parameters were not generated correctly.
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ let path = require('path'),
|
|||||||
{ DFS } = require('./dfs'),
|
{ DFS } = require('./dfs'),
|
||||||
deref = require('./deref.js'),
|
deref = require('./deref.js'),
|
||||||
{ isSwagger, getBundleRulesDataByVersion } = require('./common/versionUtils'),
|
{ isSwagger, getBundleRulesDataByVersion } = require('./common/versionUtils'),
|
||||||
CIRCULAR_REF_EXT_PROP = 'x-circularRef';
|
CIRCULAR_OR_REF_EXT_PROP = 'x-orRef';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -481,6 +481,34 @@ function findReferenceByMainKeyInTraceFromContext(documentContext, mainKeyInTrac
|
|||||||
return relatedRef;
|
return relatedRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies if a node has same content as one of the parents so it is a circular ref
|
||||||
|
* @param {function} traverseContext - The context of the traverse function
|
||||||
|
* @param {object} contentFromTrace - The resolved content of the node to deref
|
||||||
|
* @returns {boolean} whether is circular reference or not.
|
||||||
|
*/
|
||||||
|
function isCircularReference(traverseContext, contentFromTrace) {
|
||||||
|
return traverseContext.parents.find((parent) => { return parent.node === contentFromTrace; }) !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifies content of a node if it is circular reference.
|
||||||
|
*
|
||||||
|
* @param {function} traverseContext - The context of the traverse function
|
||||||
|
* @param {object} documentContext The document context from root
|
||||||
|
* @returns {undefined} nothing
|
||||||
|
*/
|
||||||
|
function handleCircularReference(traverseContext, documentContext) {
|
||||||
|
let relatedRef = '';
|
||||||
|
if (traverseContext.circular) {
|
||||||
|
relatedRef = findReferenceByMainKeyInTraceFromContext(documentContext, traverseContext.circular.key);
|
||||||
|
traverseContext.update({ $ref: relatedRef });
|
||||||
|
}
|
||||||
|
if (traverseContext.keys && traverseContext.keys.includes(CIRCULAR_OR_REF_EXT_PROP)) {
|
||||||
|
traverseContext.update({ $ref: traverseContext.node[CIRCULAR_OR_REF_EXT_PROP] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the components object from the documentContext data
|
* Generates the components object from the documentContext data
|
||||||
* @param {object} documentContext The document context from root
|
* @param {object} documentContext The document context from root
|
||||||
@@ -492,8 +520,9 @@ function findReferenceByMainKeyInTraceFromContext(documentContext, mainKeyInTrac
|
|||||||
*/
|
*/
|
||||||
function generateComponentsObject (documentContext, rootContent, refTypeResolver, components, version) {
|
function generateComponentsObject (documentContext, rootContent, refTypeResolver, components, version) {
|
||||||
let notInLine = Object.entries(documentContext.globalReferences).filter(([, value]) => {
|
let notInLine = Object.entries(documentContext.globalReferences).filter(([, value]) => {
|
||||||
return value.keyInComponents.length !== 0;
|
return value.keyInComponents.length !== 0;
|
||||||
});
|
}),
|
||||||
|
circularRefsSet = new Set();
|
||||||
const { COMPONENTS_KEYS } = getBundleRulesDataByVersion(version);
|
const { COMPONENTS_KEYS } = getBundleRulesDataByVersion(version);
|
||||||
notInLine.forEach(([key, value]) => {
|
notInLine.forEach(([key, value]) => {
|
||||||
let [, partial] = key.split(localPointer);
|
let [, partial] = key.split(localPointer);
|
||||||
@@ -541,6 +570,17 @@ function generateComponentsObject (documentContext, rootContent, refTypeResolver
|
|||||||
if (!contentFromTrace) {
|
if (!contentFromTrace) {
|
||||||
refData.nodeContent = { $ref: `${localPointer + local}` };
|
refData.nodeContent = { $ref: `${localPointer + local}` };
|
||||||
}
|
}
|
||||||
|
else if (isCircularReference(this, contentFromTrace)) {
|
||||||
|
if (refData.inline) {
|
||||||
|
refData.nodeContent = { [CIRCULAR_OR_REF_EXT_PROP]: tempRef };
|
||||||
|
circularRefsSet.add(tempRef);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
refData.node = { [CIRCULAR_OR_REF_EXT_PROP]: refData.reference };
|
||||||
|
refData.nodeContent = contentFromTrace;
|
||||||
|
circularRefsSet.add(refData.reference);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
refData.nodeContent = contentFromTrace;
|
refData.nodeContent = contentFromTrace;
|
||||||
}
|
}
|
||||||
@@ -551,39 +591,30 @@ function generateComponentsObject (documentContext, rootContent, refTypeResolver
|
|||||||
refData.node = hasSiblings ?
|
refData.node = hasSiblings ?
|
||||||
_.merge(referenceSiblings, refData.nodeContent) :
|
_.merge(referenceSiblings, refData.nodeContent) :
|
||||||
refData.nodeContent;
|
refData.nodeContent;
|
||||||
documentContext.globalReferences[property.$ref].reference =
|
documentContext.globalReferences[tempRef].reference =
|
||||||
resolveJsonPointerInlineNodes(this.parents, this.key);
|
resolveJsonPointerInlineNodes(this.parents, this.key);
|
||||||
}
|
}
|
||||||
this.update(refData.node);
|
else if (refData.refHasContent) {
|
||||||
if (!refData.inline) {
|
setValueInComponents(
|
||||||
if (documentContext.globalReferences[tempRef].refHasContent) {
|
refData.keyInComponents,
|
||||||
setValueInComponents(
|
components,
|
||||||
refData.keyInComponents,
|
refData.nodeContent,
|
||||||
components,
|
COMPONENTS_KEYS
|
||||||
refData.nodeContent,
|
);
|
||||||
COMPONENTS_KEYS
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
this.update(refData.node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
resRoot: traverseUtility(rootContent).map(function () {
|
resRoot: traverseUtility(rootContent).map(function () {
|
||||||
let relatedRef = '';
|
handleCircularReference(this, documentContext);
|
||||||
if (this.circular) {
|
|
||||||
relatedRef = findReferenceByMainKeyInTraceFromContext(documentContext, this.circular.key);
|
|
||||||
this.update({ $ref: relatedRef, [CIRCULAR_REF_EXT_PROP]: true });
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
newComponents: traverseUtility(components).map(function () {
|
newComponents: traverseUtility(components).map(function () {
|
||||||
let relatedRef = '';
|
handleCircularReference(this, documentContext);
|
||||||
if (this.circular) {
|
}),
|
||||||
relatedRef = findReferenceByMainKeyInTraceFromContext(documentContext, this.circular.key);
|
circularRefs: [...circularRefsSet]
|
||||||
this.update({ $ref: relatedRef, [CIRCULAR_REF_EXT_PROP]: true });
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,7 +649,7 @@ function generateComponentsWrapper(parsedOasObject, version, nodesContent = {})
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a map of generated refernce to the original reference
|
* Generates a map of generated reference to the original reference
|
||||||
*
|
*
|
||||||
* @param {object} globalReferences - Global references present at each root file context
|
* @param {object} globalReferences - Global references present at each root file context
|
||||||
* @returns {object} reference map
|
* @returns {object} reference map
|
||||||
@@ -712,7 +743,8 @@ module.exports = {
|
|||||||
fileContent: finalElements.resRoot,
|
fileContent: finalElements.resRoot,
|
||||||
components: finalElements.newComponents,
|
components: finalElements.newComponents,
|
||||||
fileName: specRoot.fileName,
|
fileName: specRoot.fileName,
|
||||||
referenceMap: getReferenceMap(rootContextData.globalReferences)
|
referenceMap: getReferenceMap(rootContextData.globalReferences),
|
||||||
|
circularRefs: finalElements.circularRefs
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getReferences,
|
getReferences,
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ function removeWordFromLastPosition(schemaPath, word) {
|
|||||||
* "<integer>"
|
* "<integer>"
|
||||||
*
|
*
|
||||||
* @param {string} value - Value to check for
|
* @param {string} value - Value to check for
|
||||||
* @param {string} type - The type in the schemna
|
* @param {string} type - The type in the schema
|
||||||
* @returns {Boolean} the value is the representation of its type
|
* @returns {Boolean} the value is the representation of its type
|
||||||
*/
|
*/
|
||||||
function compareType(value, type) {
|
function compareType(value, type) {
|
||||||
@@ -75,7 +75,7 @@ function compareType(value, type) {
|
|||||||
* "<integer>"
|
* "<integer>"
|
||||||
* Works in array types
|
* Works in array types
|
||||||
* @param {string} value - Value to check for
|
* @param {string} value - Value to check for
|
||||||
* @param {*} types - The types in the schemna
|
* @param {*} types - The types in the schema
|
||||||
* @returns {Boolean} the value is the representation of its type
|
* @returns {Boolean} the value is the representation of its type
|
||||||
*/
|
*/
|
||||||
function isTypeValueArrayCheck(value, types) {
|
function isTypeValueArrayCheck(value, types) {
|
||||||
@@ -89,7 +89,7 @@ function isTypeValueArrayCheck(value, types) {
|
|||||||
* "<integer>"
|
* "<integer>"
|
||||||
* Works in array types
|
* Works in array types
|
||||||
* @param {string} value - Value to check for
|
* @param {string} value - Value to check for
|
||||||
* @param {*} types - The types in the schemna
|
* @param {*} types - The types in the schema
|
||||||
* @returns {Boolean} the value is the representation of its type
|
* @returns {Boolean} the value is the representation of its type
|
||||||
*/
|
*/
|
||||||
function checkValueOnlyTypes(value, types) {
|
function checkValueOnlyTypes(value, types) {
|
||||||
@@ -118,7 +118,7 @@ function getDefaultFromTypeAndFormat(type, format) {
|
|||||||
* @returns {Boolean} the value is the representation of its type
|
* @returns {Boolean} the value is the representation of its type
|
||||||
*/
|
*/
|
||||||
function checkValueTypesAndFormat(value, types, format) {
|
function checkValueTypesAndFormat(value, types, format) {
|
||||||
let typesNotInMapp = [],
|
let typesNotInMap = [],
|
||||||
typesArray = Array.isArray(types) ? types : [types],
|
typesArray = Array.isArray(types) ? types : [types],
|
||||||
found = typesArray.find((type) => {
|
found = typesArray.find((type) => {
|
||||||
let defaultValue;
|
let defaultValue;
|
||||||
@@ -132,7 +132,7 @@ function checkValueTypesAndFormat(value, types, format) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
typesNotInMapp.push(type);
|
typesNotInMap.push(type);
|
||||||
}
|
}
|
||||||
return defaultValue === value;
|
return defaultValue === value;
|
||||||
});
|
});
|
||||||
@@ -141,7 +141,7 @@ function checkValueTypesAndFormat(value, types, format) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
found = typesNotInMapp.find((type) => {
|
found = typesNotInMap.find((type) => {
|
||||||
let defaultValue;
|
let defaultValue;
|
||||||
defaultValue = '<' + type + (format ? ('-' + format) : '') + '>';
|
defaultValue = '<' + type + (format ? ('-' + format) : '') + '>';
|
||||||
return defaultValue === value;
|
return defaultValue === value;
|
||||||
@@ -185,7 +185,7 @@ function isTypeValue(value, schema) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if value is correcta according to schema
|
* Checks if value is correct according to schema
|
||||||
* If the value should be numeric, it tries to convert and then validate
|
* If the value should be numeric, it tries to convert and then validate
|
||||||
* also validates if the value is a correct representation in the form of
|
* also validates if the value is a correct representation in the form of
|
||||||
* <long> or <integer> etc for integers format 32 or format 64
|
* <long> or <integer> etc for integers format 32 or format 64
|
||||||
@@ -332,7 +332,7 @@ module.exports = {
|
|||||||
isTypeValue,
|
isTypeValue,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if value is correcta according to schema
|
* Checks if value is correct according to schema
|
||||||
* If the value should be numeric, it tries to convert and then validate
|
* If the value should be numeric, it tries to convert and then validate
|
||||||
* also validates if the value is a correct representation in the form of
|
* also validates if the value is a correct representation in the form of
|
||||||
* <long> or <integer> etc for integers format 32 or format 64
|
* <long> or <integer> etc for integers format 32 or format 64
|
||||||
|
|||||||
@@ -1827,6 +1827,10 @@ module.exports = {
|
|||||||
bodyData = this.convertToPmBodyData(contentObj[FORM_DATA], requestType, FORM_DATA,
|
bodyData = this.convertToPmBodyData(contentObj[FORM_DATA], requestType, FORM_DATA,
|
||||||
PARAMETER_SOURCE.REQUEST, options.indentCharacter, components, options, schemaCache);
|
PARAMETER_SOURCE.REQUEST, options.indentCharacter, components, options, schemaCache);
|
||||||
encoding = contentObj[FORM_DATA].encoding ? contentObj[FORM_DATA].encoding : {};
|
encoding = contentObj[FORM_DATA].encoding ? contentObj[FORM_DATA].encoding : {};
|
||||||
|
|
||||||
|
if (contentObj[FORM_DATA].hasOwnProperty('schema') && contentObj[FORM_DATA].schema.hasOwnProperty('$ref')) {
|
||||||
|
contentObj[FORM_DATA].schema = this.getRefObject(contentObj[FORM_DATA].schema.$ref, components, options);
|
||||||
|
}
|
||||||
// create the form parameters and add it to the request body object
|
// create the form parameters and add it to the request body object
|
||||||
_.forOwn(bodyData, (value, key) => {
|
_.forOwn(bodyData, (value, key) => {
|
||||||
|
|
||||||
@@ -2454,9 +2458,6 @@ module.exports = {
|
|||||||
pmBody = this.convertToPmBody(reqBody, REQUEST_TYPE.ROOT, components, options, schemaCache);
|
pmBody = this.convertToPmBody(reqBody, REQUEST_TYPE.ROOT, components, options, schemaCache);
|
||||||
item.request.body = pmBody.body;
|
item.request.body = pmBody.body;
|
||||||
|
|
||||||
// Following is added to make sure body pruning for request methods like GET, HEAD etc is disabled'.
|
|
||||||
item.protocolProfileBehavior = { disableBodyPruning: true };
|
|
||||||
|
|
||||||
if (!options.keepImplicitHeaders || (!_.find(reqParams.header, (h) => {
|
if (!options.keepImplicitHeaders || (!_.find(reqParams.header, (h) => {
|
||||||
return _.toLower(_.get(h, 'name')) === 'content-type';
|
return _.toLower(_.get(h, 'name')) === 'content-type';
|
||||||
}))) {
|
}))) {
|
||||||
@@ -2568,6 +2569,13 @@ module.exports = {
|
|||||||
if (!_.isEmpty(acceptHeader) && !item.request.headers.has('accept')) {
|
if (!_.isEmpty(acceptHeader) && !item.request.headers.has('accept')) {
|
||||||
item.request.addHeader(acceptHeader);
|
item.request.addHeader(acceptHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Following is added to make sure body pruning for request methods like GET, HEAD etc is disabled'.
|
||||||
|
* https://github.com/postmanlabs/postman-runtime/blob/develop/docs/protocol-profile-behavior.md
|
||||||
|
*/
|
||||||
|
item.protocolProfileBehavior = { disableBodyPruning: true };
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "openapi-to-postmanv2",
|
"name": "openapi-to-postmanv2",
|
||||||
"version": "3.2.0",
|
"version": "4.0.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "openapi-to-postmanv2",
|
"name": "openapi-to-postmanv2",
|
||||||
"version": "3.2.0",
|
"version": "4.0.0",
|
||||||
"description": "Convert a given OpenAPI specification to Postman Collection v2.0",
|
"description": "Convert a given OpenAPI specification to Postman Collection v2.0",
|
||||||
"homepage": "https://github.com/postmanlabs/openapi-to-postman",
|
"homepage": "https://github.com/postmanlabs/openapi-to-postman",
|
||||||
"bugs": "https://github.com/postmanlabs/openapi-to-postman/issues",
|
"bugs": "https://github.com/postmanlabs/openapi-to-postman/issues",
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
"schema": {
|
"schema": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/components/schemas/_schemas_schemas.yaml-components_schemas_ErrorDetail"
|
"$ref": "#/components/schemas/_schemas_schemas.yaml-_components_schemas_ErrorDetail"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"_schemas_schemas.yaml-components_schemas_ErrorDetail": {
|
"_schemas_schemas.yaml-_components_schemas_ErrorDetail": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The error detail.",
|
"description": "The error detail.",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -63,8 +63,7 @@
|
|||||||
"readOnly": true,
|
"readOnly": true,
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/components/schemas/_schemas_schemas.yaml-components_schemas_ErrorDetail",
|
"$ref": "#/components/schemas/_schemas_schemas.yaml-_components_schemas_ErrorDetail"
|
||||||
"x-circularRef": true
|
|
||||||
},
|
},
|
||||||
"description": "The error details."
|
"description": "The error details."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,4 +25,4 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: "./schemas/schemas.yaml#components/schemas/ErrorDetail"
|
$ref: "./schemas/schemas.yaml#/components/schemas/ErrorDetail"
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.2",
|
||||||
|
"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 alesuada ac...",
|
||||||
|
"operationId": "findPets",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "An paged array of pets",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/_schemas_schemas.yaml-_components_schemas_ErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"_schemas_schemas.yaml-_components_schemas_ErrorResponse": {
|
||||||
|
"title": "Error response",
|
||||||
|
"description": "Common error response for all Azure Resource Manager APIs to return error details for failed operations. (This also follows the OData error response format.).",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"error": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "The error detail.",
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"readOnly": true,
|
||||||
|
"type": "string",
|
||||||
|
"description": "The error code."
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"readOnly": true,
|
||||||
|
"type": "string",
|
||||||
|
"description": "The error message."
|
||||||
|
},
|
||||||
|
"target": {
|
||||||
|
"readOnly": true,
|
||||||
|
"type": "string",
|
||||||
|
"description": "The error target."
|
||||||
|
},
|
||||||
|
"details": {
|
||||||
|
"readOnly": true,
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "/schemas/schemas.yaml#components/schemas/ErrorDetail"
|
||||||
|
},
|
||||||
|
"description": "The error details."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
openapi: "3.0.2"
|
||||||
|
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 alesuada ac...
|
||||||
|
operationId: findPets
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: An paged array of pets
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "./schemas/schemas.yaml#/components/schemas/ErrorResponse"
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
ErrorDetail:
|
||||||
|
type: object
|
||||||
|
description: The error detail.
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
readOnly: true
|
||||||
|
type: string
|
||||||
|
description: The error code.
|
||||||
|
message:
|
||||||
|
readOnly: true
|
||||||
|
type: string
|
||||||
|
description: The error message.
|
||||||
|
target:
|
||||||
|
readOnly: true
|
||||||
|
type: string
|
||||||
|
description: The error target.
|
||||||
|
details:
|
||||||
|
readOnly: true
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#components/schemas/ErrorDetail"
|
||||||
|
description: The error details.
|
||||||
|
ErrorResponse:
|
||||||
|
title: "Error response"
|
||||||
|
description: "Common error response for all Azure Resource Manager APIs to return error details for failed operations. (This also follows the OData error response format.)."
|
||||||
|
type: "object"
|
||||||
|
properties:
|
||||||
|
error:
|
||||||
|
description: "The error object."
|
||||||
|
$ref: "#components/schemas/ErrorDetail"
|
||||||
328
test/data/valid_openapi/all-http-methods.yaml
Normal file
328
test/data/valid_openapi/all-http-methods.yaml
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
openapi: "3.0.0"
|
||||||
|
info:
|
||||||
|
version: 1.0.0
|
||||||
|
title: Swagger Petstore
|
||||||
|
license:
|
||||||
|
name: MIT
|
||||||
|
servers:
|
||||||
|
- url: http://petstore.swagger.io/v1
|
||||||
|
paths:
|
||||||
|
/pets:
|
||||||
|
get:
|
||||||
|
summary: List all pets
|
||||||
|
operationId: listPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
description: How many items to return at one time (max 100)
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A paged array of pets
|
||||||
|
headers:
|
||||||
|
x-next:
|
||||||
|
description: A link to the next page of responses
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
post:
|
||||||
|
summary: List all pets
|
||||||
|
operationId: listPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
description: How many items to return at one time (max 100)
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A paged array of pets
|
||||||
|
headers:
|
||||||
|
x-next:
|
||||||
|
description: A link to the next page of responses
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
put:
|
||||||
|
summary: List all pets
|
||||||
|
operationId: listPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
description: How many items to return at one time (max 100)
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A paged array of pets
|
||||||
|
headers:
|
||||||
|
x-next:
|
||||||
|
description: A link to the next page of responses
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
patch:
|
||||||
|
summary: List all pets
|
||||||
|
operationId: listPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
description: How many items to return at one time (max 100)
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A paged array of pets
|
||||||
|
headers:
|
||||||
|
x-next:
|
||||||
|
description: A link to the next page of responses
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
delete:
|
||||||
|
summary: List all pets
|
||||||
|
operationId: listPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
description: How many items to return at one time (max 100)
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A paged array of pets
|
||||||
|
headers:
|
||||||
|
x-next:
|
||||||
|
description: A link to the next page of responses
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
head:
|
||||||
|
summary: List all pets
|
||||||
|
operationId: listPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
description: How many items to return at one time (max 100)
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A paged array of pets
|
||||||
|
headers:
|
||||||
|
x-next:
|
||||||
|
description: A link to the next page of responses
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
options:
|
||||||
|
summary: List all pets
|
||||||
|
operationId: listPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
description: How many items to return at one time (max 100)
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A paged array of pets
|
||||||
|
headers:
|
||||||
|
x-next:
|
||||||
|
description: A link to the next page of responses
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
trace:
|
||||||
|
summary: List all pets
|
||||||
|
operationId: listPets
|
||||||
|
tags:
|
||||||
|
- pets
|
||||||
|
parameters:
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
description: How many items to return at one time (max 100)
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A paged array of pets
|
||||||
|
headers:
|
||||||
|
x-next:
|
||||||
|
description: A link to the next page of responses
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Pets"
|
||||||
|
default:
|
||||||
|
description: unexpected error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Error"
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Pet:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
|
Pets:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/Pet"
|
||||||
|
Error:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- code
|
||||||
|
- message
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
33
test/data/valid_openapi/form_data_param_description.yaml
Normal file
33
test/data/valid_openapi/form_data_param_description.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
openapi: 3.0.1
|
||||||
|
info:
|
||||||
|
title: My REST API
|
||||||
|
version: 1.0.0
|
||||||
|
paths:
|
||||||
|
/description-test:
|
||||||
|
post:
|
||||||
|
description: Endpoint description
|
||||||
|
operationId: description-test
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
multipart/form-data:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/RequestSchema'
|
||||||
|
responses:
|
||||||
|
"201":
|
||||||
|
description: Response description
|
||||||
|
content:
|
||||||
|
application/json;charset=UTF-8:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
responseParam:
|
||||||
|
type: string
|
||||||
|
description: Response param description
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
RequestSchema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
requestParam:
|
||||||
|
type: string
|
||||||
|
description: Request param description
|
||||||
@@ -50,7 +50,9 @@ describe('CONVERT FUNCTION TESTS ', function() {
|
|||||||
issue10229 = path.join(__dirname, VALID_OPENAPI_PATH, '/issue#10229.json'),
|
issue10229 = path.join(__dirname, VALID_OPENAPI_PATH, '/issue#10229.json'),
|
||||||
deepObjectLengthProperty = path.join(__dirname, VALID_OPENAPI_PATH, '/deepObjectLengthProperty.yaml'),
|
deepObjectLengthProperty = path.join(__dirname, VALID_OPENAPI_PATH, '/deepObjectLengthProperty.yaml'),
|
||||||
valuePropInExample = path.join(__dirname, VALID_OPENAPI_PATH, '/valuePropInExample.yaml'),
|
valuePropInExample = path.join(__dirname, VALID_OPENAPI_PATH, '/valuePropInExample.yaml'),
|
||||||
petstoreParamExample = path.join(__dirname, VALID_OPENAPI_PATH, '/petstoreParamExample.yaml');
|
petstoreParamExample = path.join(__dirname, VALID_OPENAPI_PATH, '/petstoreParamExample.yaml'),
|
||||||
|
formDataParamDescription = path.join(__dirname, VALID_OPENAPI_PATH, '/form_data_param_description.yaml'),
|
||||||
|
allHTTPMethodsSpec = path.join(__dirname, VALID_OPENAPI_PATH, '/all-http-methods.yaml');
|
||||||
|
|
||||||
|
|
||||||
it('Should add collection level auth with type as `bearer`' +
|
it('Should add collection level auth with type as `bearer`' +
|
||||||
@@ -1141,7 +1143,39 @@ describe('CONVERT FUNCTION TESTS ', function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('[Github #559]Should convert description in form data parameters' +
|
||||||
|
petstoreParamExample, function(done) {
|
||||||
|
var openapi = fs.readFileSync(formDataParamDescription, 'utf8');
|
||||||
|
Converter.convert({ type: 'string', data: openapi },
|
||||||
|
{ }, (err, conversionResult) => {
|
||||||
|
expect(err).to.be.null;
|
||||||
|
expect(conversionResult.result).to.equal(true);
|
||||||
|
expect(conversionResult.output[0].data.item[0].request.body.formdata[0].description)
|
||||||
|
.to.equal('Request param description');
|
||||||
|
expect(conversionResult.output[0].data.item[0].request.body.formdata[0].key).to.equal('requestParam');
|
||||||
|
expect(conversionResult.output[0].data.item[0].request.body.formdata[0].value).to.equal('<string>');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should have disableBodyPruning option for protocolProfileBehavior set to true for all types of request' +
|
||||||
|
allHTTPMethodsSpec, function (done) {
|
||||||
|
var openapi = fs.readFileSync(allHTTPMethodsSpec, 'utf8');
|
||||||
|
|
||||||
|
Converter.convert({ type: 'string', data: openapi },
|
||||||
|
{}, (err, conversionResult) => {
|
||||||
|
expect(err).to.be.null;
|
||||||
|
expect(conversionResult.result).to.equal(true);
|
||||||
|
|
||||||
|
_.forEach(conversionResult.output[0].data.item[0].item, (request) => {
|
||||||
|
expect(request.protocolProfileBehavior.disableBodyPruning).to.eql(true);
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Converting swagger 2.0 files', function() {
|
describe('Converting swagger 2.0 files', function() {
|
||||||
it('should convert path paramters to postman-compatible paramters', function (done) {
|
it('should convert path paramters to postman-compatible paramters', function (done) {
|
||||||
const fileData = path.join(__dirname, SWAGGER_20_FOLDER_JSON, 'swagger2-with-params.json'),
|
const fileData = path.join(__dirname, SWAGGER_20_FOLDER_JSON, 'swagger2-with-params.json'),
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ let expect = require('chai').expect,
|
|||||||
referencedPathSchema = path.join(__dirname, BUNDLES_FOLDER + '/paths_schema'),
|
referencedPathSchema = path.join(__dirname, BUNDLES_FOLDER + '/paths_schema'),
|
||||||
exampleValue = path.join(__dirname, BUNDLES_FOLDER + '/example_value'),
|
exampleValue = path.join(__dirname, BUNDLES_FOLDER + '/example_value'),
|
||||||
example2 = path.join(__dirname, BUNDLES_FOLDER + '/example2'),
|
example2 = path.join(__dirname, BUNDLES_FOLDER + '/example2'),
|
||||||
schemaCircularRef = path.join(__dirname, BUNDLES_FOLDER + '/circular_reference');
|
schemaCircularRef = path.join(__dirname, BUNDLES_FOLDER + '/circular_reference'),
|
||||||
|
schemaCircularRefInline = path.join(__dirname, BUNDLES_FOLDER + '/circular_reference_inline');
|
||||||
|
|
||||||
describe('bundle files method - 3.0', function () {
|
describe('bundle files method - 3.0', function () {
|
||||||
it('Should return bundled file as json - schema_from_response', async function () {
|
it('Should return bundled file as json - schema_from_response', async function () {
|
||||||
@@ -2646,6 +2647,38 @@ describe('bundle files method - 3.0', function () {
|
|||||||
expect(res.output.specification.version).to.equal('3.0');
|
expect(res.output.specification.version).to.equal('3.0');
|
||||||
expect(JSON.stringify(JSON.parse(res.output.data[0].bundledContent), null, 2)).to.be.equal(expected);
|
expect(JSON.stringify(JSON.parse(res.output.data[0].bundledContent), null, 2)).to.be.equal(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should resolve circular reference in schema correctly resolved inline', async function () {
|
||||||
|
let contentRootFile = fs.readFileSync(schemaCircularRefInline + '/root.yaml', 'utf8'),
|
||||||
|
schema = fs.readFileSync(schemaCircularRefInline + '/schemas/schemas.yaml', 'utf8'),
|
||||||
|
expected = fs.readFileSync(schemaCircularRefInline + '/expected.json', 'utf8'),
|
||||||
|
input = {
|
||||||
|
type: 'multiFile',
|
||||||
|
specificationVersion: '3.0',
|
||||||
|
rootFiles: [
|
||||||
|
{
|
||||||
|
path: '/root.yaml'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
path: '/root.yaml',
|
||||||
|
content: contentRootFile
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/schemas/schemas.yaml',
|
||||||
|
content: schema
|
||||||
|
}
|
||||||
|
],
|
||||||
|
options: {},
|
||||||
|
bundleFormat: 'JSON'
|
||||||
|
};
|
||||||
|
const res = await Converter.bundle(input);
|
||||||
|
expect(res).to.not.be.empty;
|
||||||
|
expect(res.result).to.be.true;
|
||||||
|
expect(res.output.specification.version).to.equal('3.0');
|
||||||
|
expect(JSON.stringify(JSON.parse(res.output.data[0].bundledContent), null, 2)).to.be.equal(expected);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getReferences method when node does not have any reference', function() {
|
describe('getReferences method when node does not have any reference', function() {
|
||||||
|
|||||||
Reference in New Issue
Block a user