diff --git a/test/data/validationData/emptyParameterCollection.json b/test/data/validationData/emptyParameterCollection.json new file mode 100644 index 0000000..17615d7 --- /dev/null +++ b/test/data/validationData/emptyParameterCollection.json @@ -0,0 +1,134 @@ +{ + "item": [ + { + "id": "448f9fe2-0057-4d55-a369-80d41162b8a6", + "name": "pets", + "description": { + "content": "", + "type": "text/plain" + }, + "item": [ + { + "id": "6ee42234-271d-490c-a23a-50b70a57142c", + "name": "List all pets", + "request": { + "name": "List all pets", + "description": {}, + "url": { + "path": [ + "pets" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [ + { + "description": "How many items to return at one time (max 100)", + "key": "limit", + "value": "89178631" + } + ], + "variable": [] + }, + "method": "GET", + "auth": null + }, + "response": [ + { + "id": "d491ab71-8cde-4fd8-9538-7896929c2309", + "name": "A paged array of pets", + "originalRequest": { + "url": { + "path": [ + "pets" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [ + { + "key": "limit", + "value": "" + } + ], + "variable": [] + }, + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "description": "A link to the next page of responses", + "key": "x-next", + "value": "velit ea si" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "[\n {\n \"id\": -14143765,\n \"name\": \"deserunt in\",\n \"tag\": \"consectetur cupidatat\"\n },\n {\n \"id\": -65226018,\n \"name\": \"ex consectetur eu in\",\n \"tag\": \"laborum mollit officia Ut\"\n }\n]", + "cookie": [], + "_postman_previewlanguage": "json" + }, + { + "id": "23ad8e8e-a752-4a5d-905e-2b63f04fb7ea", + "name": "unexpected error", + "originalRequest": { + "url": { + "path": [ + "pets" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [ + { + "key": "limit", + "value": "" + } + ], + "variable": [] + }, + "method": "GET", + "body": {} + }, + "status": "Internal Server Error", + "code": 500, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"code\": 41499321,\n \"message\": \"dolore\"\n}", + "cookie": [], + "_postman_previewlanguage": "json" + } + ], + "event": [] + } + ], + "event": [] + } + ], + "event": [], + "variable": [ + { + "id": "baseUrl", + "type": "string", + "value": "http://petstore.swagger.io/v1" + } + ], + "info": { + "_postman_id": "a60fcbcc-ec53-4cd7-a4df-7abe60ebeb84", + "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/emptyParameterSpec.yaml b/test/data/validationData/emptyParameterSpec.yaml new file mode 100644 index 0000000..8c657f5 --- /dev/null +++ b/test/data/validationData/emptyParameterSpec.yaml @@ -0,0 +1,73 @@ +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: + # below param is empty for testing + - + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + format: int32 + 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 \ No newline at end of file diff --git a/test/data/validationData/implicitHeaderCollection.json b/test/data/validationData/implicitHeaderCollection.json new file mode 100644 index 0000000..b863cd4 --- /dev/null +++ b/test/data/validationData/implicitHeaderCollection.json @@ -0,0 +1,163 @@ +{ + "item": [ + { + "id": "6e1e8783-7fae-4902-b764-b8a5c2632139", + "name": "pets", + "description": { + "content": "", + "type": "text/plain" + }, + "item": [ + { + "id": "46d9bd4b-c82c-454b-93e5-dcdf64798497", + "name": "Create a pet", + "request": { + "name": "Create a pet", + "description": {}, + "url": { + "path": [ + "pets" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "description": "", + "key": "Accept", + "value": "application/json" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": "", + "key": "header-1", + "value": "not a number" + } + ], + "method": "POST", + "auth": null, + "body": { + "mode": "raw", + "raw": "{\n \"id\": 11265533,\n \"name\": \"tempor adipisicin\",\n \"tag\": \"sint culpa veniam\"\n}" + } + }, + "response": [ + { + "id": "34840c21-65c2-42f6-8a6d-280a4f800849", + "name": "Null response", + "originalRequest": { + "url": { + "path": [ + "pets" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "description": "", + "key": "Accept", + "value": "" + }, + { + "description": "", + "key": "header-1", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"id\": 11265533,\n \"name\": \"tempor adipisicin\",\n \"tag\": \"sint culpa veniam\"\n}" + } + }, + "status": "Created", + "code": 201, + "header": [ + { + "key": "Content-Type", + "value": "text/plain" + } + ], + "body": "", + "cookie": [], + "_postman_previewlanguage": "text" + }, + { + "id": "7aaf6fcb-2af9-4c4f-a650-b004101b6cf5", + "name": "unexpected error", + "originalRequest": { + "url": { + "path": [ + "pets" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "description": "", + "key": "Accept", + "value": "" + }, + { + "description": "", + "key": "header-1", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"id\": 11265533,\n \"name\": \"tempor adipisicin\",\n \"tag\": \"sint culpa veniam\"\n}" + } + }, + "status": "Internal Server Error", + "code": 500, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"code\": 22640796,\n \"message\": \"aute\"\n}", + "cookie": [], + "_postman_previewlanguage": "json" + } + ], + "event": [] + } + ], + "event": [] + } + ], + "event": [], + "variable": [ + { + "id": "baseUrl", + "type": "string", + "value": "http://petstore.swagger.io/v1" + } + ], + "info": { + "_postman_id": "2d5ffaea-40bd-4f22-8bc7-e951deeacdf6", + "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/implicitHeaderSpec.yaml b/test/data/validationData/implicitHeaderSpec.yaml new file mode 100644 index 0000000..028daaf --- /dev/null +++ b/test/data/validationData/implicitHeaderSpec.yaml @@ -0,0 +1,71 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT +servers: + - url: http://petstore.swagger.io/v1 +paths: + /pets: + post: + summary: Create a pet + operationId: createPets + tags: + - pets + parameters: + - name: Accept + in: header + required: false + schema: + type: string + - name: header-1 + in: header + required: false + schema: + type: integer + format: int32 + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + responses: + '201': + description: Null response + 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 \ No newline at end of file diff --git a/test/data/validationData/rootKeywordViolationCollection.json b/test/data/validationData/rootKeywordViolationCollection.json new file mode 100644 index 0000000..fef8038 --- /dev/null +++ b/test/data/validationData/rootKeywordViolationCollection.json @@ -0,0 +1,145 @@ +{ + "item": [ + { + "id": "6a23e0c5-f874-4d64-917f-436e8b6630b7", + "name": "pets", + "description": { + "content": "", + "type": "text/plain" + }, + "item": [ + { + "id": "58a1eaab-6150-4bd8-9606-aae2a519d1dc", + "name": "Create a pet", + "request": { + "name": "Create a pet", + "description": {}, + "url": { + "path": [ + "pets" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [ + { + "description": "", + "key": "limit", + "value": "-74270672" + } + ], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "method": "POST", + "auth": null, + "body": { + "mode": "raw", + "raw": "{\n \"id\": -97299140,\n \"name\": \"dolore\",\n \"tag\": \"nostrud et in\"\n}" + } + }, + "response": [ + { + "id": "497bb8cc-bf09-4712-b3c2-38a7f7772e00", + "name": "Null response", + "originalRequest": { + "url": { + "path": [ + "pets" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [ + { + "key": "limit", + "value": "" + } + ], + "variable": [] + }, + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"id\": -97299140,\n \"name\": \"dolore\",\n \"tag\": \"nostrud et in\"\n}" + } + }, + "status": "Created", + "code": 201, + "header": [ + { + "key": "Content-Type", + "value": "text/plain" + } + ], + "body": "", + "cookie": [], + "_postman_previewlanguage": "text" + }, + { + "id": "51d2030f-e874-4b29-b8b7-a92de6566ec0", + "name": "unexpected error", + "originalRequest": { + "url": { + "path": [ + "pets" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [ + { + "key": "limit", + "value": "" + } + ], + "variable": [] + }, + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"id\": -97299140,\n \"name\": \"dolore\",\n \"tag\": \"nostrud et in\"\n}" + } + }, + "status": "Internal Server Error", + "code": 500, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"code\": 94595733,\n \"message\": \"Duis sit qui\"\n}", + "cookie": [], + "_postman_previewlanguage": "json" + } + ], + "event": [] + } + ], + "event": [] + } + ], + "event": [], + "variable": [ + { + "id": "baseUrl", + "type": "string", + "value": "http://petstore.swagger.io/v1" + } + ], + "info": { + "_postman_id": "9836d256-0ada-42d6-a825-a103d0bb3695", + "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/rootKeywordViolationSpec.yaml b/test/data/validationData/rootKeywordViolationSpec.yaml new file mode 100644 index 0000000..2b5d18e --- /dev/null +++ b/test/data/validationData/rootKeywordViolationSpec.yaml @@ -0,0 +1,63 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT +servers: + - url: http://petstore.swagger.io/v1 +paths: + /pets: + post: + summary: Create a pet + operationId: createPets + tags: + - pets + parameters: + - name: limit + in: query + required: false + schema: + type: integer + format: int32 + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" +components: + schemas: + Pet: + type: object + minProperties: 4 + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string \ No newline at end of file diff --git a/test/unit/validator.test.js b/test/unit/validator.test.js index 698a547..de6fcdc 100644 --- a/test/unit/validator.test.js +++ b/test/unit/validator.test.js @@ -376,3 +376,84 @@ describe('The Validation option', function () { }); }); }); + +describe('VALIDATE FUNCTION TESTS ', function () { + describe('validateTransaction function', function () { + it('Should not fail if spec to validate contains empty parameters', function (done) { + let emptyParameterSpec = fs.readFileSync(path.join(__dirname, VALIDATION_DATA_FOLDER_PATH + + '/emptyParameterSpec.yaml'), 'utf-8'), + emptyParameterCollection = fs.readFileSync(path.join(__dirname, VALIDATION_DATA_FOLDER_PATH + + '/emptyParameterCollection.json'), 'utf-8'), + resultObj, + historyRequest = [], + schemaPack = new Converter.SchemaPack({ type: 'string', data: emptyParameterSpec }, {}); + + getAllTransactions(JSON.parse(emptyParameterCollection), historyRequest); + + schemaPack.validateTransaction(historyRequest, (err, result) => { + // Schema is sample petsore with one of parameter as empty, expect no mismatch / error + 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(); + }); + }); + + it('Should correctly handle transactionPath property when Implicit headers are present', function (done) { + let implicitHeaderSpec = fs.readFileSync(path.join(__dirname, VALIDATION_DATA_FOLDER_PATH + + '/implicitHeaderSpec.yaml'), 'utf-8'), + implicitHeaderCollection = fs.readFileSync(path.join(__dirname, VALIDATION_DATA_FOLDER_PATH + + '/implicitHeaderCollection.json'), 'utf-8'), + resultObj, + historyRequest = [], + schemaPack = new Converter.SchemaPack({ type: 'string', data: implicitHeaderSpec }, {}); + + getAllTransactions(JSON.parse(implicitHeaderCollection), 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(1); + + /** + header-1 is invalid according to schema, as request contains other 2 implicit headers(Content-Type and Accept) + the mismatch for header-1 should contain correct index as in request. + */ + expect(_.endsWith(resultObj.mismatches[0].transactionJsonPath, '[2].value')).to.eql(true); + done(); + }); + }); + + it('Should correctly suggest value when violated keyword is at root level', function (done) { + let rootKeywordViolationSpec = fs.readFileSync(path.join(__dirname, VALIDATION_DATA_FOLDER_PATH + + '/rootKeywordViolationSpec.yaml'), 'utf-8'), + rootKeywordViolationCollection = fs.readFileSync(path.join(__dirname, VALIDATION_DATA_FOLDER_PATH + + '/rootKeywordViolationCollection.json'), 'utf-8'), + options = { suggestAvailableFixes: true }, + resultObj, + historyRequest = [], + schemaPack = new Converter.SchemaPack({ type: 'string', data: rootKeywordViolationSpec }, options); + + getAllTransactions(JSON.parse(rootKeywordViolationCollection), 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(1); + + /** + The spec contains "POST /pet" endpoint with request body as Pet object which requires minimum property of 4 + as this property is root (Json path to prop is ''(empty), we expect suggested value to be according to spec) + */ + expect(_.keys(resultObj.mismatches[0].suggestedFix.actualValue)).to.have.lengthOf(3); + expect(_.keys(resultObj.mismatches[0].suggestedFix.suggestedValue)).to.have.lengthOf(4); + done(); + }); + }); + }); +});