Skip to content

Commit e255040

Browse files
committed
Merge branch 'release/4.9.0'
2 parents d4efdd8 + 36f8c0a commit e255040

File tree

10 files changed

+166
-12
lines changed

10 files changed

+166
-12
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# OpenAPI-Postman Changelog
22

3+
#### v4.9.0 (February 06, 2023)
4+
* Fixed issue [#660](https://github.com/postmanlabs/openapi-to-postman/issues/660) where for certain XML request bodies, conversion was failing with TypeError.
5+
* Fixed issue where for some definitions having non-string URLs were failing conversion with TypeErrors.
6+
* Fixed issue where a test in-consistently kept failing due to uncertainity of jsf library.
7+
38
#### v4.8.0 (January 24, 2023)
49
* Added specifictionVersion field to validate result.
510

lib/31XUtils/schemaUtils31X.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ module.exports = {
125125
schema.items = this.fixExamplesByVersion(schema.items);
126126
}
127127
else if (hasProperties) {
128-
const schemaProperties = Object.keys(schema.properties);
128+
const schemaProperties = _.keys(schema.properties);
129129
schemaProperties.forEach((property) => {
130130
schema.properties[property] = this.fixExamplesByVersion(schema.properties[property]);
131131
});
@@ -141,7 +141,7 @@ module.exports = {
141141
* @returns {boolean} Returns true if content is a binary type
142142
*/
143143
isBinaryContentType (bodyType, contentObj) {
144-
return Object.keys(contentObj[bodyType]).length === 0 && fileUploadTypes.includes(bodyType);
144+
return _.keys(contentObj[bodyType]).length === 0 && fileUploadTypes.includes(bodyType);
145145
},
146146

147147
getOuterPropsIfIsSupported(schema) {
@@ -152,7 +152,7 @@ module.exports = {
152152

153153
addOuterPropsToRefSchemaIfIsSupported(refSchema, outerProps) {
154154
const resolvedSchema = _.cloneDeep(refSchema),
155-
outerKeys = Object.keys(outerProps);
155+
outerKeys = _.keys(outerProps);
156156

157157
if (_.isObject(resolvedSchema) && _.isObject(outerProps)) {
158158
outerKeys.forEach((key) => {

lib/schemaUtils.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,13 @@ function safeSchemaFaker (oldSchema, resolveTo, resolveFor, parameterSourceOptio
196196
});
197197
}
198198

199+
if (schemaFormat === 'xml') {
200+
key += ' schemaFormatXML';
201+
}
202+
else {
203+
key += ' schemaFormatDEFAULT';
204+
}
205+
199206
key = hash(key);
200207
if (schemaFakerCache[key]) {
201208
return schemaFakerCache[key];
@@ -360,6 +367,11 @@ module.exports = {
360367
* @returns {string} string after replacing /{pet}/ with /:pet/
361368
*/
362369
fixPathVariablesInUrl: function (url) {
370+
// URL should always be string so update value if non-string value is found
371+
if (typeof url !== 'string') {
372+
return '';
373+
}
374+
363375
// All complicated logic removed
364376
// This simply replaces all instances of {text} with {{text}}
365377
// text cannot have any of these 3 chars: /{}
@@ -371,7 +383,7 @@ module.exports = {
371383
}
372384
return '{' + p1 + '}';
373385
};
374-
return url.replace(/(\{[^\/\{\}]+\})/g, replacer);
386+
return _.isString(url) ? url.replace(/(\{[^\/\{\}]+\})/g, replacer) : '';
375387
},
376388

377389
/**
@@ -2797,7 +2809,7 @@ module.exports = {
27972809
// also, any endpoint-level params are merged into the returned pathItemObject
27982810
findMatchingRequestFromSchema: function (method, url, schema, options) {
27992811
// first step - get array of requests from schema
2800-
let parsedUrl = require('url').parse(url),
2812+
let parsedUrl = require('url').parse(_.isString(url) ? url : ''),
28012813
retVal = [],
28022814
pathToMatch,
28032815
matchedPath,

lib/xmlSchemaFaker.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
4747
attributes.push(`${key}="${propVal}"`);
4848
}
4949
else {
50-
childNodes += propVal;
50+
childNodes += _.isString(propVal) ? propVal : '';
5151
}
5252
});
5353
if (attributes.length > 0) {
@@ -66,7 +66,7 @@ function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
6666
contents;
6767

6868
schemaItemsWithXmlProps.xml = schema.xml;
69-
contents = convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar, indent + extraIndent) +
69+
contents = convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar, indent + extraIndent) +
7070
convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar, indent + extraIndent);
7171
if (isWrapped) {
7272
return `\n${cIndent}<${tagPrefix}${name}>${contents}\n${cIndent}</${tagPrefix}${name}>`;

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openapi-to-postmanv2",
3-
"version": "4.8.0",
3+
"version": "4.9.0",
44
"description": "Convert a given OpenAPI specification to Postman Collection v2.0",
55
"homepage": "https://github.com/postmanlabs/openapi-to-postman",
66
"bugs": "https://github.com/postmanlabs/openapi-to-postman/issues",

test/unit/31Xsupport/schemaUtils31X.test.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,26 @@ describe('fixExamplesByVersion method', function() {
624624
expect(JSON.stringify(fixedSchemaWithExample)).to.be.equal(JSON.stringify(expectedSchemaAfterFix));
625625
});
626626

627+
it('Should correctly handle schema with properties defined as null', function() {
628+
const providedSchema = {
629+
required: [
630+
'id',
631+
'name'
632+
],
633+
type: 'object',
634+
properties: null
635+
},
636+
expectedSchemaAfterFix = {
637+
required: [
638+
'id',
639+
'name'
640+
],
641+
type: 'object',
642+
properties: null
643+
},
644+
fixedSchemaWithExample = concreteUtils.fixExamplesByVersion(providedSchema);
645+
expect(JSON.stringify(fixedSchemaWithExample)).to.be.equal(JSON.stringify(expectedSchemaAfterFix));
646+
});
627647
});
628648

629649
describe('isBinaryContentType method', function() {
@@ -651,6 +671,15 @@ describe('isBinaryContentType method', function() {
651671
isBinary = concreteUtils.isBinaryContentType(bodyType, contentObject);
652672
expect(isBinary).to.be.false;
653673
});
674+
675+
it('Should correctly handle null value for corresponding body', function() {
676+
const bodyType = 'application/octet-stream',
677+
contentObject = {
678+
'application/octet-stream': null
679+
},
680+
isBinary = concreteUtils.isBinaryContentType(bodyType, contentObject);
681+
expect(isBinary).to.be.true;
682+
});
654683
});
655684

656685
describe('getOuterPropsIfIsSupported method', function() {
@@ -704,6 +733,22 @@ describe('getOuterPropsIfIsSupported method', function() {
704733
expect(resolvedSchema.job).to.be.equal(outerProperties.job);
705734
expect(JSON.stringify(resolvedSchema.required)).to.be.equal(JSON.stringify(expectedRequiredValue));
706735
});
736+
737+
it('Should correctly handle if outer properties are defined as null', function() {
738+
const referencedSchema = {
739+
name: 'Test name',
740+
age: '30',
741+
required: [
742+
'name'
743+
]
744+
},
745+
outerProperties = null,
746+
expectedRequiredValue = ['name'],
747+
resolvedSchema = concreteUtils.addOuterPropsToRefSchemaIfIsSupported(referencedSchema, outerProperties);
748+
expect(resolvedSchema).to.be.an('object')
749+
.nested.to.have.all.keys('name', 'age', 'required');
750+
expect(JSON.stringify(resolvedSchema.required)).to.be.equal(JSON.stringify(expectedRequiredValue));
751+
});
707752
});
708753

709754
describe('findTypeByExample method', function () {

test/unit/base.test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1816,7 +1816,9 @@ describe('CONVERT FUNCTION TESTS ', function() {
18161816
const responseBodyWithAdditionalProperties =
18171817
JSON.parse(conversionResult.output[0].data.item[0].response[1].body);
18181818
expect(responseBodyWithAdditionalProperties).to.include.keys('test1');
1819-
expect(Object.keys(responseBodyWithAdditionalProperties).length).to.be.greaterThan(1);
1819+
1820+
// json-schema-faker doesn't guarantee that there will always be additional properties generated
1821+
expect(Object.keys(responseBodyWithAdditionalProperties).length).to.be.greaterThanOrEqual(1);
18201822
done();
18211823
});
18221824
});

test/unit/util.test.js

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ describe('SCHEMA UTILITY FUNCTION TESTS ', function () {
206206
schemaCache = {
207207
schemaFakerCache: {}
208208
},
209-
key = hash('resolveToSchema ' + JSON.stringify(resolvedSchema)),
209+
key = hash('resolveToSchema ' + JSON.stringify(resolvedSchema) + ' schemaFormatDEFAULT'),
210210
options = {
211211
indentCharacter: ' ',
212212
stackLimit: 10,
@@ -251,7 +251,7 @@ describe('SCHEMA UTILITY FUNCTION TESTS ', function () {
251251
{ components, concreteUtils },
252252
{ resolveFor, resolveTo }
253253
),
254-
key = hash('resolveToExample ' + JSON.stringify(resolvedSchema)),
254+
key = hash('resolveToExample ' + JSON.stringify(resolvedSchema) + ' schemaFormatDEFAULT'),
255255
options = {
256256
indentCharacter: ' ',
257257
stackLimit: 10,
@@ -268,6 +268,60 @@ describe('SCHEMA UTILITY FUNCTION TESTS ', function () {
268268
done();
269269

270270
});
271+
272+
it('should populate schemaFakerCache with distinct value when only the schemaFormat is different', function (done) {
273+
var schema = {
274+
$ref: '#/components/schema/request'
275+
},
276+
components = {
277+
schema: {
278+
request: {
279+
properties: {
280+
name: {
281+
type: 'string'
282+
}
283+
}
284+
}
285+
}
286+
},
287+
parameterSource = 'REQUEST',
288+
resolveTo = 'schema',
289+
resolveFor = 'CONVERSION',
290+
resolvedSchema = deref.resolveRefs(schema,
291+
parameterSource,
292+
{ components, concreteUtils },
293+
{ resolveFor, resolveTo }
294+
),
295+
schemaCache = {
296+
schemaFakerCache: {}
297+
},
298+
xml_key = hash('resolveToSchema ' + JSON.stringify(resolvedSchema) + ' schemaFormatXML'),
299+
default_key = hash('resolveToSchema ' + JSON.stringify(resolvedSchema) + ' schemaFormatDEFAULT'),
300+
options = {
301+
indentCharacter: ' ',
302+
stackLimit: 10,
303+
includeDeprecated: true
304+
},
305+
fakedSchema_default = SchemaUtils.safeSchemaFaker(schema, resolveTo, resolveFor, parameterSource,
306+
{ components, concreteUtils }, 'default', schemaCache, options),
307+
fakedSchema_xml = SchemaUtils.safeSchemaFaker(schema, resolveTo, resolveFor, parameterSource,
308+
{ components, concreteUtils }, 'xml', schemaCache, options);
309+
310+
expect(schemaCache.schemaFakerCache).to.have.property(default_key);
311+
expect(schemaCache.schemaFakerCache[default_key]).to.equal(fakedSchema_default);
312+
expect(fakedSchema_default).to.eql({
313+
name: '<string>'
314+
});
315+
316+
expect(schemaCache.schemaFakerCache).to.have.property(xml_key);
317+
expect(schemaCache.schemaFakerCache[xml_key]).to.equal(fakedSchema_xml);
318+
expect(fakedSchema_xml).to.eql(
319+
'<element>\n <name>(string)</name>\n</element>'
320+
);
321+
322+
done();
323+
});
324+
271325
});
272326

273327
describe('convertToPmCollectionVariables function', function() {
@@ -2577,6 +2631,13 @@ describe('SCHEMA UTILITY FUNCTION TESTS ', function () {
25772631
});
25782632

25792633
describe('fixPathVariablesInUrl function', function() {
2634+
it('should be able to handle incorrect urls', function(done) {
2635+
expect(SchemaUtils.fixPathVariablesInUrl({})).to.equal('');
2636+
expect(SchemaUtils.fixPathVariablesInUrl(null)).to.equal('');
2637+
expect(SchemaUtils.fixPathVariablesInUrl(undefined)).to.equal('');
2638+
done();
2639+
});
2640+
25802641
it('should convert a url with scheme and path variables', function(done) {
25812642
var convertedUrl = SchemaUtils.fixPathVariablesInUrl('{scheme}://developer.uspto.gov/{path0}/segment/{path1}');
25822643
expect(convertedUrl).to.equal('{{scheme}}://developer.uspto.gov/{{path0}}/segment/{{path1}}');
@@ -2593,6 +2654,18 @@ describe('SCHEMA UTILITY FUNCTION TESTS ', function () {
25932654

25942655
done();
25952656
});
2657+
2658+
it('should correctly handle non string values', function(done) {
2659+
expect(SchemaUtils.fixPathVariablesInUrl(123)).to.equal('');
2660+
2661+
expect(SchemaUtils.fixPathVariablesInUrl([])).to.equal('');
2662+
2663+
expect(SchemaUtils.fixPathVariablesInUrl({})).to.equal('');
2664+
2665+
expect(SchemaUtils.fixPathVariablesInUrl(true)).to.equal('');
2666+
2667+
done();
2668+
});
25962669
});
25972670

25982671
describe('findPathVariablesFromPath function', function() {

test/unit/validator.test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,23 @@ describe('VALIDATE FUNCTION TESTS ', function () {
14041404
expect(result[1].name).to.eql('GET /lookups');
14051405
done();
14061406
});
1407+
1408+
it('should correctly handle non string URLs', function (done) {
1409+
let schema = {
1410+
paths: {
1411+
'/lookups': {
1412+
'get': { 'summary': 'Lookup Job Values' }
1413+
}
1414+
}
1415+
},
1416+
schemaPath = null,
1417+
result;
1418+
1419+
result = schemaUtils.findMatchingRequestFromSchema('GET', schemaPath, schema, { strictRequestMatching: true });
1420+
1421+
expect(result).to.have.lengthOf(0);
1422+
done();
1423+
});
14071424
});
14081425
});
14091426

0 commit comments

Comments
 (0)