diff --git a/lib/schemaUtils.js b/lib/schemaUtils.js index e203f1d..33332c1 100644 --- a/lib/schemaUtils.js +++ b/lib/schemaUtils.js @@ -2873,6 +2873,13 @@ module.exports = { let reason = '', mismatchObj; + // exclude mismatch errors for nested objects in parameters (at this point simple objects and array should + // be already converted to primitive schema and only nested objects remains as type object/array) + if (_.includes(['QUERYPARAM', 'PATHVARIABLE', 'HEADER'], property) && + (schema.type === 'object' || schema.type === 'array')) { + return callback(null, []); + } + if (property === 'RESPONSE_BODY' || property === 'BODY') { // we don't have names for the body, but there's only one reason = 'The ' + humanPropName; diff --git a/test/data/validationData/nestedObjectParamsCollection.json b/test/data/validationData/nestedObjectParamsCollection.json new file mode 100644 index 0000000..57a8f83 --- /dev/null +++ b/test/data/validationData/nestedObjectParamsCollection.json @@ -0,0 +1,136 @@ +{ + "item": [ + { + "id": "a2b99009-5e11-43ac-b411-fa7fd1425262", + "name": "pets", + "description": { + "content": "", + "type": "text/plain" + }, + "item": [ + { + "id": "099ccc06-611e-4e31-8462-7e66ba7783e7", + "name": "List all pets", + "request": { + "name": "List all pets", + "description": {}, + "url": { + "path": [ + "pets" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [ + { + "disabled": false, + "key": "limit", + "value": "prop2,32,prop1,[object Object]", + "description": "(Required) How many items to return at one time (max 100)" + } + ], + "variable": [] + }, + "method": "GET", + "auth": null + }, + "response": [ + { + "id": "24e8f452-28f2-44a2-839e-081e2d54c287", + "name": "An paged array of pets", + "originalRequest": { + "url": { + "path": [ + "pets" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [ + { + "key": "limit", + "value": "prop2,32,prop1,[object Object]" + } + ], + "variable": [] + }, + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "disabled": false, + "description": "A link to the next page of responses", + "key": "x-next", + "value": "nostrud do" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "[\n {\n \"id\": 17889649,\n \"name\": \"enim tempor minim\",\n \"tag\": \"incididunt esse nostrud culpa sit\"\n },\n {\n \"id\": 54275385,\n \"name\": \"et labore veniam\",\n \"tag\": \"elit ut si\"\n }\n]", + "cookie": [], + "_postman_previewlanguage": "json" + }, + { + "id": "5b174b95-db8c-4a53-9a89-a817b47e9d1b", + "name": "unexpected error", + "originalRequest": { + "url": { + "path": [ + "pets" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [ + { + "key": "limit", + "value": "prop2,32,prop1,[object Object]" + } + ], + "variable": [] + }, + "method": "GET", + "body": {} + }, + "status": "Internal Server Error", + "code": 500, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"code\": -28330006,\n \"message\": \"qui occaecat magna\"\n}", + "cookie": [], + "_postman_previewlanguage": "json" + } + ], + "event": [] + } + ], + "event": [] + } + ], + "event": [], + "variable": [ + { + "type": "string", + "value": "http://petstore.swagger.io/v1", + "key": "baseUrl" + } + ], + "info": { + "_postman_id": "0861b241-23ad-435c-a80e-af77f30b2acd", + "name": "Swagger Petstore", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "description": { + "content": "", + "type": "text/plain" + } + } +} \ No newline at end of file diff --git a/test/data/validationData/nestedObjectParamsSpec.yaml b/test/data/validationData/nestedObjectParamsSpec.yaml new file mode 100644 index 0000000..4d3316b --- /dev/null +++ b/test/data/validationData/nestedObjectParamsSpec.yaml @@ -0,0 +1,80 @@ +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: true + explode: false + schema: + type: object + required: + - prop2 + properties: + prop1: + type: object + properties: + prop1_1: + type: string + prop2: + type: integer + example: 32 + responses: + '200': + description: An 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: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" + Error: + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string diff --git a/test/unit/validator.test.js b/test/unit/validator.test.js index 49ba378..51276f0 100644 --- a/test/unit/validator.test.js +++ b/test/unit/validator.test.js @@ -613,6 +613,33 @@ describe('VALIDATE FUNCTION TESTS ', function () { done(); }); }); + + it('Should ignore mismatches for nested objects in parameters', function (done) { + let nestedObjectParamsSpec = fs.readFileSync(path.join(__dirname, VALIDATION_DATA_FOLDER_PATH + + '/nestedObjectParamsSpec.yaml'), 'utf-8'), + nestedObjectParamsCollection = fs.readFileSync(path.join(__dirname, VALIDATION_DATA_FOLDER_PATH + + '/nestedObjectParamsCollection.json'), 'utf-8'), + resultObj, + historyRequest = [], + options = { + showMissingInSchemaErrors: true, + strictRequestMatching: true, + ignoreUnresolvedVariables: true, + suggestAvailableFixes: true + }, + schemaPack = new Converter.SchemaPack({ type: 'string', data: nestedObjectParamsSpec }, options); + + getAllTransactions(JSON.parse(nestedObjectParamsCollection), historyRequest); + + schemaPack.validateTransaction(historyRequest, (err, result) => { + expect(err).to.be.null; + expect(result).to.be.an('object'); + + resultObj = result.requests[historyRequest[0].id].endpoints[0]; + expect(resultObj.mismatches).to.have.lengthOf(0); + done(); + }); + }); }); describe('getPostmanUrlSuffixSchemaScore function', function () {