From e8046bc62eabd70b5b03821adfbe9ac2b52e7567 Mon Sep 17 00:00:00 2001 From: Vishal Shingala Date: Tue, 26 Mar 2024 12:46:58 +0530 Subject: [PATCH 1/3] Fixed an issue where schemas under allOf keyword having additionalProperties set to false were not generating bodies correctly --- lib/deref.js | 2 + libV2/schemaUtils.js | 2 + .../allOfAdditionalProperties.json | 157 ++++++++++++++++++ test/unit/convertV2.test.js | 22 +++ test/unit/deref.test.js | 70 ++++++++ 5 files changed, 253 insertions(+) create mode 100644 test/data/valid_openapi/allOfAdditionalProperties.json diff --git a/lib/deref.js b/lib/deref.js index 7bbcabbd..baa2e589 100644 --- a/lib/deref.js +++ b/lib/deref.js @@ -131,6 +131,8 @@ module.exports = { { stack, seenRef: _.cloneDeep(seenRef), resolveFor, resolveTo, stackLimit, isAllOf: true, analytics }); }) }), { + // below option is required to make sure schemas with additionalProperties set to false are resolved correctly + ignoreAdditionalProperties: true, resolvers: { // for keywords in OpenAPI schema that are not standard defined JSON schema keywords, use default resolver defaultResolver: (compacted) => { return compacted[0]; }, diff --git a/libV2/schemaUtils.js b/libV2/schemaUtils.js index 1e3be334..3fbf47ab 100644 --- a/libV2/schemaUtils.js +++ b/libV2/schemaUtils.js @@ -456,6 +456,8 @@ let QUERYPARAM = 'query', return resolveSchema(context, schema, stack, resolveFor, _.cloneDeep(seenRef)); }) }), { + // below option is required to make sure schemas with additionalProperties set to false are resolved correctly + ignoreAdditionalProperties: true, resolvers: { // for keywords in OpenAPI schema that are not standard defined JSON schema keywords, use default resolver defaultResolver: (compacted) => { return compacted[0]; }, diff --git a/test/data/valid_openapi/allOfAdditionalProperties.json b/test/data/valid_openapi/allOfAdditionalProperties.json new file mode 100644 index 00000000..f7fd10e1 --- /dev/null +++ b/test/data/valid_openapi/allOfAdditionalProperties.json @@ -0,0 +1,157 @@ +{ + "x-generator": "NSwag v14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))", + "openapi": "3.0.0", + "info": { + "title": "Join API", + "version": "1.0.0" + }, + "paths": { + "/api/Membership": { + "post": { + "tags": [ + "Membership" + ], + "operationId": "PostMember", + "requestBody": { + "x-name": "query", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardJoinCommand" + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardJoinDto" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "GetMemberDto": { + "type": "object", + "additionalProperties": false, + "properties": { + "memberId": { + "type": "integer", + "format": "int32" + }, + "username": { + "type": "string", + "nullable": true + }, + "comment": { + "type": "string", + "nullable": true + }, + "email": { + "type": "string", + "nullable": true + } + } + }, + "StandardJoinDto": { + "allOf": [ + { + "$ref": "#/components/schemas/BaseJoinDto" + }, + { + "type": "object", + "additionalProperties": false + } + ] + }, + "BaseJoinDto": { + "type": "object", + "additionalProperties": false, + "properties": { + "memberId": { + "type": "integer", + "format": "int32" + }, + "firstName": { + "type": "string", + "nullable": true + }, + "lastName": { + "type": "string", + "nullable": true + } + } + }, + "StandardJoinCommand": { + "allOf": [ + { + "$ref": "#/components/schemas/BaseJoinCommandOfStandardJoinDto" + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "email": { + "type": "string", + "nullable": true + }, + "firstName": { + "type": "string", + "nullable": true + }, + "lastName": { + "type": "string", + "nullable": true + }, + "address1": { + "type": "string", + "nullable": true + }, + "city": { + "type": "string", + "nullable": true + }, + "state": { + "type": "string" + }, + "countryCode": { + "type": "string", + "nullable": true + }, + "zipCode": { + "type": "string", + "nullable": true + }, + "phoneNumber": { + "type": "string", + "nullable": true + } + } + } + ] + }, + "BaseJoinCommandOfStandardJoinDto": { + "type": "object", + "x-abstract": true, + "additionalProperties": false, + "properties": { + "campaignId": { + "type": "integer", + "format": "int32" + } + } + } + } + } +} + diff --git a/test/unit/convertV2.test.js b/test/unit/convertV2.test.js index 85c9d99f..41852bb1 100644 --- a/test/unit/convertV2.test.js +++ b/test/unit/convertV2.test.js @@ -2091,6 +2091,28 @@ describe('The convert v2 Function', function() { }); }); + it('[GITHUB #417] - should convert file with allOf schemas containing additionalProperties as false ', function() { + const fileSource = path.join(__dirname, VALID_OPENAPI_PATH, 'allOfAdditionalProperties.json'), + fileData = fs.readFileSync(fileSource, 'utf8'), + input = { + type: 'string', + data: fileData + }; + + Converter.convertV2(input, { + optimizeConversion: false + }, (err, result) => { + const expectedRequestBody = JSON.parse(result.output[0].data.item[0].item[0].item[0].request.body.raw); + + expect(err).to.be.null; + expect(result.result).to.be.true; + + expect(expectedRequestBody).to.be.an('object'); + expect(expectedRequestBody).to.have.keys(['phoneNumber', 'zipCode', 'countryCode', 'state', 'city', + 'address1', 'lastName', 'firstName', 'email', 'campaignId']); + }); + }); + it('Should convert a swagger document with XML example correctly', function(done) { const fileData = fs.readFileSync(path.join(__dirname, SWAGGER_20_FOLDER_YAML, 'xml_example.yaml'), 'utf8'), input = { diff --git a/test/unit/deref.test.js b/test/unit/deref.test.js index 9d99a5b0..c318ebd9 100644 --- a/test/unit/deref.test.js +++ b/test/unit/deref.test.js @@ -516,6 +516,76 @@ describe('DEREF FUNCTION TESTS ', function() { }); done(); }); + + it('should resolve schemas under allOf keyword with additionalProperties set to false correctly', function (done) { + var schema = { + 'allOf': [ + { + 'type': 'object', + 'additionalProperties': false, + 'properties': { + 'source': { + 'type': 'string', + 'format': 'uuid' + }, + 'status': { + 'type': 'string', + 'enum': ['incomplete', 'completed', 'refunded'] + }, + 'actionId': { 'type': 'integer', 'minimum': 5 }, + 'result': { 'type': 'object' } + }, + 'required': ['source', 'actionId', 'result'] + }, + { + 'additionalProperties': false, + 'properties': { + 'result': { + 'type': 'object', + 'properties': { + 'err': { 'type': 'string' }, + 'data': { 'type': 'object' } + } + }, + 'status': { + 'type': 'string', + 'enum': ['no_market', 'too_small', 'too_large'] + } + } + } + ] + }; + + expect(deref.resolveAllOf( + schema, + 'REQUEST', + { concreteUtils: schemaUtils30X }, + { resolveTo: 'example' } + )).to.deep.equal({ + type: 'object', + additionalProperties: false, + required: ['source', 'actionId', 'result'], + properties: { + source: { + type: 'string', + format: 'uuid' + }, + status: { + type: 'string', + enum: ['incomplete', 'completed', 'refunded', 'no_market', 'too_small', 'too_large'] + }, + actionId: { 'type': 'integer', 'minimum': 5 }, + result: { + type: 'object', + properties: { + err: { 'type': 'string' }, + data: { 'type': 'object' } + } + } + } + }); + done(); + }); }); describe('_getEscaped should', function() { From 3e1e4e8ee19b60ea7947c6086ea776fb9c4869cf Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Wed, 27 Mar 2024 12:58:38 +0000 Subject: [PATCH 2/3] Prepare release v4.20.1 --- CHANGELOG.md | 6 +++++- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c81b6f38..c81d74dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## [Unreleased] +## [v4.20.1] - 2024-03-27 + ## [v4.20.0] - 2024-02-15 ### Added @@ -608,7 +610,9 @@ Newer releases follow the [Keep a Changelog](https://keepachangelog.com/en/1.0.0 - Base release -[Unreleased]: https://github.com/postmanlabs/openapi-to-postman/compare/v4.20.0...HEAD +[Unreleased]: https://github.com/postmanlabs/openapi-to-postman/compare/v4.20.1...HEAD + +[v4.20.1]: https://github.com/postmanlabs/openapi-to-postman/compare/v4.20.0...v4.20.1 [v4.20.0]: https://github.com/postmanlabs/openapi-to-postman/compare/v4.19.0...v4.20.0 diff --git a/package-lock.json b/package-lock.json index e53adc6f..9bc695f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "openapi-to-postmanv2", - "version": "4.20.0", + "version": "4.20.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "openapi-to-postmanv2", - "version": "4.20.0", + "version": "4.20.1", "license": "Apache-2.0", "dependencies": { "ajv": "8.11.0", diff --git a/package.json b/package.json index ff9b5789..1e29f3c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openapi-to-postmanv2", - "version": "4.20.0", + "version": "4.20.1", "description": "Convert a given OpenAPI specification to Postman Collection v2.0", "homepage": "https://github.com/postmanlabs/openapi-to-postman", "bugs": "https://github.com/postmanlabs/openapi-to-postman/issues", From 0128b3d2a776f9128cfc57f7e2d2827b1441cd78 Mon Sep 17 00:00:00 2001 From: Vishal Shingala Date: Wed, 27 Mar 2024 18:31:42 +0530 Subject: [PATCH 3/3] Added changelogs --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c81d74dd..c2edfa55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ## [v4.20.1] - 2024-03-27 +### Fixed + +- Fixed an issue where schemas under allOf keyword having additionalProperties set to false were not generating bodies correctly. + ## [v4.20.0] - 2024-02-15 ### Added