From 2fa418ddb0a37515347747f1b0843299f767280e Mon Sep 17 00:00:00 2001 From: Melsy Huamani Date: Fri, 20 Feb 2026 09:20:24 -0500 Subject: [PATCH 1/8] feat: update 3.1 versions range --- src/parser/version.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/version.js b/src/parser/version.js index 0563ab1..65945f2 100644 --- a/src/parser/version.js +++ b/src/parser/version.js @@ -7,7 +7,7 @@ module.exports = function() { return function get(){ const versions = { swagger : ['2.0', '2.0.0'], - openapi : ['3.0', '3.0.0', '3.0.1','3.0.2' , '3.0.3'] + openapi : ['3.0', '3.0.0', '3.0.1','3.0.2', '3.0.3', '3.1.0', '3.1.1', '3.1.2'] } if (versions.swagger.includes(global.definition.swagger)) { From de98b353c4fe7142d3a3a33648f9d2a31b83fd3c Mon Sep 17 00:00:00 2001 From: Melsy Huamani Date: Thu, 26 Feb 2026 16:31:31 -0500 Subject: [PATCH 2/8] fix: tests for swagger 2 and openapi 3.0 --- seeds/generatorEndpointsResult.json | 530 ++++++++++++++-------------- seeds/generatorFoldersResult.json | 90 ++--- seeds/generatorTestBodyResult.json | 100 +++++- src/generator/endpoints.js | 18 +- src/generator/folders.js | 4 +- src/parser/openapi3/body.js | 22 +- src/parser/openapi3/queryParams.js | 41 ++- src/parser/swagger2/body.js | 3 +- src/parser/swagger2/queryParams.js | 55 +-- test/generator-endpoints.js | 2 +- test/generator-examples.js | 2 +- test/generator-folders.js | 2 +- test/parser-body.js | 2 +- test/parser-endpoints.js | 6 +- 14 files changed, 507 insertions(+), 370 deletions(-) diff --git a/seeds/generatorEndpointsResult.json b/seeds/generatorEndpointsResult.json index 0f0ea6f..1160f27 100644 --- a/seeds/generatorEndpointsResult.json +++ b/seeds/generatorEndpointsResult.json @@ -1,282 +1,282 @@ -[ - { - "name":"/pets-200", - "aux":{ - "status":"200", - "body":false, - "consumes":false, - "bodyResponse":false, - "authorization":false, - "summary":false, - "queryParams":false, - "pathParameter":false +[ + { + "name": "/pets-200", + "path": "/pets", + "count": 1, + "microcks": false, + "aux": { + "status": "200", + "body": false, + "consumes": false, + "bodyResponse": false, + "authorization": false, + "summary": false, + "queryParams": false, + "pathParameter": null, + "pathParameterExample": "" + }, + "response": [], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" }, - "response":[ - - ], - "request":{ - "method":"GET", - "header":[ - - ], - "body":{ - "mode":"raw", - "raw":"" - }, - "url":{ - "raw":"{{host}}{{port}}{{basePath}}/pets", - "host":[ - "{{host}}{{port}}{{basePath}}" - ], - "path":[ - "/pets" - ] - } + "url": { + "raw": "{{host}}{{port}}{{basePath}}/pets", + "host": [ + "{{host}}{{port}}{{basePath}}" + ], + "path": [ + "pets" + ] } - }, - { - "name":"/pets-500", - "aux":{ - "status":"500", - "body":false, - "consumes":false, - "bodyResponse":false, - "authorization":false, - "summary":false, - "queryParams":false, - "pathParameter":false + } + }, + { + "name": "/pets-500", + "path": "/pets", + "count": 1, + "microcks": false, + "aux": { + "status": "500", + "body": false, + "consumes": false, + "bodyResponse": false, + "authorization": false, + "summary": false, + "queryParams": false, + "pathParameter": null, + "pathParameterExample": "" + }, + "response": [], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" }, - "response":[ - - ], - "request":{ - "method":"GET", - "header":[ - - ], - "body":{ - "mode":"raw", - "raw":"" - }, - "url":{ - "raw":"{{host}}{{port}}{{basePath}}/pets", - "host":[ - "{{host}}{{port}}{{basePath}}" - ], - "path":[ - "/pets" - ] - } + "url": { + "raw": "{{host}}{{port}}{{basePath}}/pets", + "host": [ + "{{host}}{{port}}{{basePath}}" + ], + "path": [ + "pets" + ] } - }, - { - "name":"/pets-200", - "aux":{ - "status":"200", - "body":false, - "consumes":false, - "bodyResponse":false, - "authorization":false, - "summary":false, - "queryParams":false, - "pathParameter":false + } + }, + { + "name": "/pets-200", + "path": "/pets", + "count": 1, + "microcks": false, + "aux": { + "status": "200", + "body": false, + "consumes": false, + "bodyResponse": false, + "authorization": false, + "summary": false, + "queryParams": false, + "pathParameter": null, + "pathParameterExample": "" + }, + "response": [], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "" }, - "response":[ - - ], - "request":{ - "method":"POST", - "header":[ - - ], - "body":{ - "mode":"raw", - "raw":"" - }, - "url":{ - "raw":"{{host}}{{port}}{{basePath}}/pets", - "host":[ - "{{host}}{{port}}{{basePath}}" - ], - "path":[ - "/pets" - ] - } + "url": { + "raw": "{{host}}{{port}}{{basePath}}/pets", + "host": [ + "{{host}}{{port}}{{basePath}}" + ], + "path": [ + "pets" + ] } - }, - { - "name":"/pets-500", - "aux":{ - "status":"500", - "body":false, - "consumes":false, - "bodyResponse":false, - "authorization":false, - "summary":false, - "queryParams":false, - "pathParameter":false + } + }, + { + "name": "/pets-500", + "path": "/pets", + "count": 1, + "microcks": false, + "aux": { + "status": "500", + "body": false, + "consumes": false, + "bodyResponse": false, + "authorization": false, + "summary": false, + "queryParams": false, + "pathParameter": null, + "pathParameterExample": "" + }, + "response": [], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "" }, - "response":[ - - ], - "request":{ - "method":"POST", - "header":[ - - ], - "body":{ - "mode":"raw", - "raw":"" - }, - "url":{ - "raw":"{{host}}{{port}}{{basePath}}/pets", - "host":[ - "{{host}}{{port}}{{basePath}}" - ], - "path":[ - "/pets" - ] - } + "url": { + "raw": "{{host}}{{port}}{{basePath}}/pets", + "host": [ + "{{host}}{{port}}{{basePath}}" + ], + "path": [ + "pets" + ] } - }, - { - "name":"/pets/{id}-200", - "aux":{ - "status":"200", - "body":false, - "consumes":false, - "bodyResponse":false, - "authorization":false, - "summary":false, - "queryParams":false, - "pathParameter":false + } + }, + { + "name": "/pets/{id}-200", + "path": "/pets/{id}", + "count": 1, + "microcks": false, + "aux": { + "status": "200", + "body": false, + "consumes": false, + "bodyResponse": false, + "authorization": false, + "summary": false, + "queryParams": false, + "pathParameter": null, + "pathParameterExample": "" + }, + "response": [], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" }, - "response":[ - - ], - "request":{ - "method":"GET", - "header":[ - - ], - "body":{ - "mode":"raw", - "raw":"" - }, - "url":{ - "raw":"{{host}}{{port}}{{basePath}}/pets/{id}", - "host":[ - "{{host}}{{port}}{{basePath}}" - ], - "path":[ - "/pets/{id}" - ] - } + "url": { + "raw": "{{host}}{{port}}{{basePath}}/pets/{id}", + "host": [ + "{{host}}{{port}}{{basePath}}" + ], + "path": [ + "pets/{id}" + ] } - }, - { - "name":"/pets/{id}-500", - "aux":{ - "status":"500", - "body":false, - "consumes":false, - "bodyResponse":false, - "authorization":false, - "summary":false, - "queryParams":false, - "pathParameter":false + } + }, + { + "name": "/pets/{id}-500", + "path": "/pets/{id}", + "count": 1, + "microcks": false, + "aux": { + "status": "500", + "body": false, + "consumes": false, + "bodyResponse": false, + "authorization": false, + "summary": false, + "queryParams": false, + "pathParameter": null, + "pathParameterExample": "" + }, + "response": [], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" }, - "response":[ - - ], - "request":{ - "method":"GET", - "header":[ - - ], - "body":{ - "mode":"raw", - "raw":"" - }, - "url":{ - "raw":"{{host}}{{port}}{{basePath}}/pets/{id}", - "host":[ - "{{host}}{{port}}{{basePath}}" - ], - "path":[ - "/pets/{id}" - ] - } + "url": { + "raw": "{{host}}{{port}}{{basePath}}/pets/{id}", + "host": [ + "{{host}}{{port}}{{basePath}}" + ], + "path": [ + "pets/{id}" + ] } - }, - { - "name":"/pets/{id}-204", - "aux":{ - "status":"204", - "body":false, - "consumes":false, - "bodyResponse":false, - "authorization":false, - "summary":false, - "queryParams":false, - "pathParameter":false + } + }, + { + "name": "/pets/{id}-204", + "path": "/pets/{id}", + "count": 1, + "microcks": false, + "aux": { + "status": "204", + "body": false, + "consumes": false, + "bodyResponse": false, + "authorization": false, + "summary": false, + "queryParams": false, + "pathParameter": null, + "pathParameterExample": "" + }, + "response": [], + "request": { + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "" }, - "response":[ - - ], - "request":{ - "method":"DELETE", - "header":[ - - ], - "body":{ - "mode":"raw", - "raw":"" - }, - "url":{ - "raw":"{{host}}{{port}}{{basePath}}/pets/{id}", - "host":[ - "{{host}}{{port}}{{basePath}}" - ], - "path":[ - "/pets/{id}" - ] - } + "url": { + "raw": "{{host}}{{port}}{{basePath}}/pets/{id}", + "host": [ + "{{host}}{{port}}{{basePath}}" + ], + "path": [ + "pets/{id}" + ] } - }, - { - "name":"/pets/{id}-500", - "aux":{ - "status":"500", - "body":false, - "consumes":false, - "bodyResponse":false, - "authorization":false, - "summary":false, - "queryParams":false, - "pathParameter":false + } + }, + { + "name": "/pets/{id}-500", + "path": "/pets/{id}", + "count": 1, + "microcks": false, + "aux": { + "status": "500", + "body": false, + "consumes": false, + "bodyResponse": false, + "authorization": false, + "summary": false, + "queryParams": false, + "pathParameter": null, + "pathParameterExample": "" + }, + "response": [], + "request": { + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "" }, - "response":[ - - ], - "request":{ - "method":"DELETE", - "header":[ - - ], - "body":{ - "mode":"raw", - "raw":"" - }, - "url":{ - "raw":"{{host}}{{port}}{{basePath}}/pets/{id}", - "host":[ - "{{host}}{{port}}{{basePath}}" - ], - "path":[ - "/pets/{id}" - ] - } + "url": { + "raw": "{{host}}{{port}}{{basePath}}/pets/{id}", + "host": [ + "{{host}}{{port}}{{basePath}}" + ], + "path": [ + "pets/{id}" + ] } - } + } + } ] \ No newline at end of file diff --git a/seeds/generatorFoldersResult.json b/seeds/generatorFoldersResult.json index 5bd601a..a7f4121 100644 --- a/seeds/generatorFoldersResult.json +++ b/seeds/generatorFoldersResult.json @@ -6,7 +6,7 @@ "name":"001.001.uploads an image", "item":[ { - "name":"TC.001.001.200 uploads an image ", + "name":"TC.001.001.200", "aux":{ "status":"200", "body":false, @@ -97,7 +97,7 @@ "name":"001.002.Update an existing pet", "item":[ { - "name":"TC.001.002.400 Update an existing pet without.name", + "name":"TC.001.002.400 without.name", "aux":{ "status":"400", "body":{ @@ -272,7 +272,7 @@ ] }, { - "name":"TC.001.002.400 Update an existing pet without.photoUrls", + "name":"TC.001.002.400 without.photoUrls", "aux":{ "status":"400", "body":{ @@ -444,7 +444,7 @@ ] }, { - "name":"TC.001.002.400 Update an existing pet with.id.wrong", + "name":"TC.001.002.400 with.id.wrong", "aux":{ "status":"400", "body":{ @@ -619,7 +619,7 @@ ] }, { - "name":"TC.001.002.400 Update an existing pet with.category.wrong", + "name":"TC.001.002.400 with.category.wrong", "aux":{ "status":"400", "body":{ @@ -794,7 +794,7 @@ ] }, { - "name":"TC.001.002.400 Update an existing pet with.category.id.wrong", + "name":"TC.001.002.400 with.category.id.wrong", "aux":{ "status":"400", "body":{ @@ -969,7 +969,7 @@ ] }, { - "name":"TC.001.002.400 Update an existing pet with.category.name.wrong", + "name":"TC.001.002.400 with.category.name.wrong", "aux":{ "status":"400", "body":{ @@ -1144,7 +1144,7 @@ ] }, { - "name":"TC.001.002.400 Update an existing pet with.name.wrong", + "name":"TC.001.002.400 with.name.wrong", "aux":{ "status":"400", "body":{ @@ -1319,7 +1319,7 @@ ] }, { - "name":"TC.001.002.400 Update an existing pet with.photoUrls.wrong", + "name":"TC.001.002.400 with.photoUrls.wrong", "aux":{ "status":"400", "body":{ @@ -1491,7 +1491,7 @@ ] }, { - "name":"TC.001.002.400 Update an existing pet with.tags.wrong", + "name":"TC.001.002.400 with.tags.wrong", "aux":{ "status":"400", "body":{ @@ -1656,7 +1656,7 @@ ] }, { - "name":"TC.001.002.400 Update an existing pet with.tags.id.wrong", + "name":"TC.001.002.400 with.tags.id.wrong", "aux":{ "status":"400", "body":{ @@ -1831,7 +1831,7 @@ ] }, { - "name":"TC.001.002.400 Update an existing pet with.tags.name.wrong", + "name":"TC.001.002.400 with.tags.name.wrong", "aux":{ "status":"400", "body":{ @@ -2006,7 +2006,7 @@ ] }, { - "name":"TC.001.002.400 Update an existing pet with.status.wrong", + "name":"TC.001.002.400 with.status.wrong", "aux":{ "status":"400", "body":{ @@ -2191,7 +2191,7 @@ "name":"001.003.Finds Pets by status", "item":[ { - "name":"TC.001.003.200 Finds Pets by status ", + "name":"TC.001.003.200", "aux":{ "status":"200", "body":false, @@ -2365,7 +2365,7 @@ ] }, { - "name":"TC.001.003.400 Finds Pets by status .without.status", + "name":"TC.001.003.400 .without.status", "aux":{ "status":"400", "body":false, @@ -2542,7 +2542,7 @@ "name":"001.004.Finds Pets by tags", "item":[ { - "name":"TC.001.004.200 Finds Pets by tags ", + "name":"TC.001.004.200", "aux":{ "status":"200", "body":false, @@ -2615,7 +2615,7 @@ ] }, { - "name":"TC.001.004.400 Finds Pets by tags .without.tags", + "name":"TC.001.004.400 .without.tags", "aux":{ "status":"400", "body":false, @@ -2691,7 +2691,7 @@ "name":"001.005.Find pet by ID", "item":[ { - "name":"TC.001.005.200 Find pet by ID ", + "name":"TC.001.005.200", "aux":{ "status":"200", "body":false, @@ -2857,7 +2857,7 @@ ] }, { - "name":"TC.001.005.404 Find pet by ID ", + "name":"TC.001.005.404", "aux":{ "status":"404", "body":false, @@ -3030,7 +3030,7 @@ "name":"002.001.Place an order for a pet", "item":[ { - "name":"TC.002.001.200 Place an order for a pet ", + "name":"TC.002.001.200", "aux":{ "status":"200", "body":{ @@ -3223,7 +3223,7 @@ ] }, { - "name":"TC.002.001.400 Place an order for a pet with.id.wrong", + "name":"TC.002.001.400 with.id.wrong", "aux":{ "status":"400", "body":{ @@ -3409,7 +3409,7 @@ ] }, { - "name":"TC.002.001.400 Place an order for a pet with.petId.wrong", + "name":"TC.002.001.400 with.petId.wrong", "aux":{ "status":"400", "body":{ @@ -3595,7 +3595,7 @@ ] }, { - "name":"TC.002.001.400 Place an order for a pet with.quantity.wrong", + "name":"TC.002.001.400 with.quantity.wrong", "aux":{ "status":"400", "body":{ @@ -3781,7 +3781,7 @@ ] }, { - "name":"TC.002.001.400 Place an order for a pet with.shipDate.wrong", + "name":"TC.002.001.400 with.shipDate.wrong", "aux":{ "status":"400", "body":{ @@ -3967,7 +3967,7 @@ ] }, { - "name":"TC.002.001.400 Place an order for a pet with.status.wrong", + "name":"TC.002.001.400 with.status.wrong", "aux":{ "status":"400", "body":{ @@ -4153,7 +4153,7 @@ ] }, { - "name":"TC.002.001.400 Place an order for a pet with.complete.wrong", + "name":"TC.002.001.400 with.complete.wrong", "aux":{ "status":"400", "body":{ @@ -4349,7 +4349,7 @@ "name":"002.002.Returns pet inventories by status", "item":[ { - "name":"TC.002.002.200 Returns pet inventories by status ", + "name":"TC.002.002.200", "aux":{ "status":"200", "body":false, @@ -4427,7 +4427,7 @@ "name":"002.003.Find purchase order by ID", "item":[ { - "name":"TC.002.003.200 Find purchase order by ID ", + "name":"TC.002.003.200", "aux":{ "status":"200", "body":false, @@ -4553,7 +4553,7 @@ ] }, { - "name":"TC.002.003.404 Find purchase order by ID ", + "name":"TC.002.003.404", "aux":{ "status":"404", "body":false, @@ -4681,7 +4681,7 @@ "name":"002.004.Delete purchase order by ID", "item":[ { - "name":"TC.002.004.404 Delete purchase order by ID ", + "name":"TC.002.004.404", "aux":{ "status":"404", "body":false, @@ -4750,7 +4750,7 @@ "name":"003.001.Updated user", "item":[ { - "name":"TC.003.001.400 Updated user with.id.wrong", + "name":"TC.003.001.400 with.id.wrong", "aux":{ "status":"400", "body":{ @@ -4844,7 +4844,7 @@ ] }, { - "name":"TC.003.001.400 Updated user with.username.wrong", + "name":"TC.003.001.400 with.username.wrong", "aux":{ "status":"400", "body":{ @@ -4938,7 +4938,7 @@ ] }, { - "name":"TC.003.001.400 Updated user with.firstName.wrong", + "name":"TC.003.001.400 with.firstName.wrong", "aux":{ "status":"400", "body":{ @@ -5032,7 +5032,7 @@ ] }, { - "name":"TC.003.001.400 Updated user with.lastName.wrong", + "name":"TC.003.001.400 with.lastName.wrong", "aux":{ "status":"400", "body":{ @@ -5126,7 +5126,7 @@ ] }, { - "name":"TC.003.001.400 Updated user with.email.wrong", + "name":"TC.003.001.400 with.email.wrong", "aux":{ "status":"400", "body":{ @@ -5220,7 +5220,7 @@ ] }, { - "name":"TC.003.001.400 Updated user with.password.wrong", + "name":"TC.003.001.400 with.password.wrong", "aux":{ "status":"400", "body":{ @@ -5314,7 +5314,7 @@ ] }, { - "name":"TC.003.001.400 Updated user with.phone.wrong", + "name":"TC.003.001.400 with.phone.wrong", "aux":{ "status":"400", "body":{ @@ -5408,7 +5408,7 @@ ] }, { - "name":"TC.003.001.400 Updated user with.userStatus.wrong", + "name":"TC.003.001.400 with.userStatus.wrong", "aux":{ "status":"400", "body":{ @@ -5502,7 +5502,7 @@ ] }, { - "name":"TC.003.001.404 Updated user ", + "name":"TC.003.001.404", "aux":{ "status":"404", "body":{ @@ -5605,7 +5605,7 @@ "name":"003.002.Logs user into the system", "item":[ { - "name":"TC.003.002.200 Logs user into the system ", + "name":"TC.003.002.200", "aux":{ "status":"200", "body":false, @@ -5680,7 +5680,7 @@ ] }, { - "name":"TC.003.002.400 Logs user into the system .without.username", + "name":"TC.003.002.400 .without.username", "aux":{ "status":"400", "body":false, @@ -5748,7 +5748,7 @@ ] }, { - "name":"TC.003.002.400 Logs user into the system .without.password", + "name":"TC.003.002.400 .without.password", "aux":{ "status":"400", "body":false, @@ -5826,7 +5826,7 @@ "name":"003.003.Get user by user name", "item":[ { - "name":"TC.003.003.200 Get user by user name ", + "name":"TC.003.003.200", "aux":{ "status":"200", "body":false, @@ -5924,7 +5924,7 @@ ] }, { - "name":"TC.003.003.404 Get user by user name ", + "name":"TC.003.003.404", "aux":{ "status":"404", "body":false, @@ -6024,7 +6024,7 @@ "name":"003.004.Delete user", "item":[ { - "name":"TC.003.004.404 Delete user ", + "name":"TC.003.004.404", "aux":{ "status":"404", "body":false, diff --git a/seeds/generatorTestBodyResult.json b/seeds/generatorTestBodyResult.json index 30a5940..f06b93a 100644 --- a/seeds/generatorTestBodyResult.json +++ b/seeds/generatorTestBodyResult.json @@ -1 +1,99 @@ -{"name":"/pets/{id}-200","aux":{"status":"200","body":false,"consumes":false,"bodyResponse":{"200":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}},"response":[],"request":{"method":"GET","header":[],"body":{"mode":"raw","raw":""},"url":{"raw":"{{host}}{{port}}{{basePath}}/pets/{{id}}","host":["{{host}}{{port}}{{basePath}}"],"path":["/pets/{{id}}"]}},"event":[{"listen":"test","script":{"id":"63142ff5-28a4-40b2-8314-dcbeeaa89325","type":"text/javascript","exec":["pm.test(\"Status code is 200\", function () {"," pm.response.to.have.status(200);","});","","var json = JSON.parse(responseBody);","","var schema = {\"type\":\"object\",\"required\":[\"name\",\"id\"],\"properties\":{\"name\":{\"type\":\"string\"},\"tag\":{\"type\":\"string\"},\"id\":{\"type\":\"integer\",\"format\":\"int64\"}}};","","pm.test('Schema is valid', function() {"," pm.expect(tv4.validate(json, schema)).to.be.true;","});"]}}]} \ No newline at end of file +{ + "name": "/pets/{id}-200", + "aux": { + "status": "200", + "body": false, + "consumes": false, + "bodyResponse": { + "200": { + "type": "object", + "required": [ + "name", + "id" + ], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + }, + "id": { + "type": "integer", + "format": "int64" + } + } + }, + "500": { + "type": "object", + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + } + } + } + }, + "response": [], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}{{port}}{{basePath}}/pets/{{id}}", + "host": [ + "{{host}}{{port}}{{basePath}}" + ], + "path": [ + "/pets/{{id}}" + ] + } + }, + "event": [ + { + "listen": "test", + "script": { + "id": "63142ff5-28a4-40b2-8314-dcbeeaa89325", + "type": "text/javascript", + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var json = null;", + "", + "try {", + "\tjson = pm.response.json();", + "\t// Guardar variables en environment", + "\t// pm.environment.set('nombreVariable', json.data.variable);", + "} catch (e) {", + "\tpm.test(\"A JSON response was expected\", function() {", + "\t\tpm.expect(json, \"responseBody no es un JSON\").not.to.be.null;", + "\t});", + "}", + "", + "var schema = {\"type\":\"object\",\"required\":[\"name\",\"id\"],\"properties\":{\"name\":{\"type\":\"string\"},\"tag\":{\"type\":\"string\"},\"id\":{\"type\":\"integer\",\"format\":\"int64\"}}};", + "", + "var Ajv = require(\"ajv\");", + "var ajv = new Ajv({ logger: console, allErrors: false, unknownFormats: ['int32', 'int64', 'float', 'double', 'password'] });", + "var validate = ajv.compile(schema);", + "var valid = validate(json);", + "pm.test(\"Schema is valid according to AJV\", function () {", + "\tpm.expect(valid, JSON.stringify(validate.errors, null, 2)).to.be.true;", + "});" + ] + } + } + ] +} \ No newline at end of file diff --git a/src/generator/endpoints.js b/src/generator/endpoints.js index 7b66d12..69c3e20 100644 --- a/src/generator/endpoints.js +++ b/src/generator/endpoints.js @@ -10,7 +10,7 @@ module.exports = function() { const items = []; _.forEach(endpoints, function(endpoint) { let path = endpoint.path; - let pathParameterSaved = false + let pathParameterSaved = false; _.forEach(endpoint.pathParameters, function(pathParameter) { pathParameterSaved = pathParameter; path = _.replace(path, '{'+pathParameter.name+'}', '{{'+pathParameter.name+'}}') @@ -28,8 +28,8 @@ module.exports = function() { authorization: endpoint.authorization ? endpoint.authorization : false, summary: endpoint.summary ? endpoint.summary : false, queryParams: endpoint.queryParams ? endpoint.queryParams : false, - pathParameter: pathParameterSaved.name, - pathParameterExample: pathParameterSaved.example || '', + pathParameter: pathParameterSaved?.name || null, + pathParameterExample: pathParameterSaved?.example || '', }, count: countRequest(endpoint), response: [], @@ -66,7 +66,7 @@ module.exports = function() { } // Duplicar los endpoints para cada queryParameter dependiendo si el minimal endpoint está en true o false - if(!global.configurationFile.minimal_endpoints || global.configurationFile.minimal_endpoints === false){ + if(!global.configurationFile?.minimal_endpoints || global.configurationFile?.minimal_endpoints === false){ if (item.aux.status >= 200 && item.aux.status < 400 && item.aux.queryParams.length > 0) { addQueryParamEndpoint(item, items); } @@ -114,12 +114,14 @@ module.exports = function() { } function countRequest(endpoint){ - if(!global.configurationFile.generate_oneOf_anyOf){ + if (!global.configurationFile?.generate_oneOf_anyOf) { return 1; } - if (endpoint.body) { - const found = _.find(endpoint.body, (value, key) => key === 'oneOf' || key === 'anyOf'); - if (found) { + + if (endpoint?.body && typeof endpoint.body === 'object') { + const found = endpoint.body.oneOf || endpoint.body.anyOf; + + if (Array.isArray(found)) { return found.length; } } diff --git a/src/generator/folders.js b/src/generator/folders.js index 0d501cf..7e1fd8a 100644 --- a/src/generator/folders.js +++ b/src/generator/folders.js @@ -68,10 +68,10 @@ module.exports = function() { } for (let i in collection){ let countItem = 1 - let numerateRoot = _.padStart(countRoot, 2, '0') + '.' + let numerateRoot = _.padStart(countRoot, 3, '0') + '.' collection[i].name = numerateRoot + collection[i].name for (let j in collection[i].item) { - let numerateItem = numerateRoot + _.padStart(countItem, 2, '0') + '.' + let numerateItem = numerateRoot + _.padStart(countItem, 3, '0') + '.' collection[i].item[j].name = numerateItem + collection[i].item[j].name if (!collection[i].item[j].aux){ collection[i].item[j].aux = {} diff --git a/src/parser/openapi3/body.js b/src/parser/openapi3/body.js index fcff2e3..13fc51e 100644 --- a/src/parser/openapi3/body.js +++ b/src/parser/openapi3/body.js @@ -8,17 +8,20 @@ module.exports = function() { const MAX_DEPTH_LEVEL = 20; let seenSchemas = new WeakSet(); - + return function get(verb, path, bodyResponse) { + seenSchemas = new WeakSet(); + if (!_.isObject(global.definition.paths)) { require('../../utils/error.js')('paths is required') } const endpoint = global.definition.paths[path][_.toLower(verb)] + if (!endpoint) return undefined; + if (!bodyResponse){ let body = endpoint['requestBody']; - if (!body){ - return undefined; - } + if (!body) return undefined; + if (body['$ref']) { let componentType = body['$ref'].split('/')[2] const ref = _.replace(body['$ref'], '#/components/'+componentType+'/', '') @@ -82,11 +85,13 @@ module.exports = function() { description: 'Circular REF solved swagger2postman' } } + let entity = global.definition.components[componentType][ref] if (!entity) { require('../../utils/error.js')('ref '+ref+' is not defined') } - entity = replaceRefs(entity,global.definition, ++depthLevel) + + entity = replaceRefs(entity, depthLevel + 1); result = _.merge(result, entity) } else if ( _.isArray(schema[i]) && i !== 'required') { const arrayResult = [] @@ -94,14 +99,11 @@ module.exports = function() { continue } for (const k in schema[i]) { - // arrayResult.push(replaceRefs(schema[i][k], global.definition, ++depthLevel)) - arrayResult.push(schema[i][k]) + arrayResult.push(replaceRefs(schema[i][k], depthLevel + 1)) } result[i] = arrayResult } else if ( _.isObject(schema[i]) && i !== 'required') { - ++depthLevel; - result[i] = schema[i]; - // result[i] = replaceRefs(schema[i],global.definition); + result[i] = replaceRefs(schema[i], depthLevel + 1); } else { result[i] = schema[i]; } diff --git a/src/parser/openapi3/queryParams.js b/src/parser/openapi3/queryParams.js index afc529e..59f2922 100644 --- a/src/parser/openapi3/queryParams.js +++ b/src/parser/openapi3/queryParams.js @@ -5,10 +5,9 @@ const _ = require('lodash'); module.exports = function() { - + return function get(verb,path){ if (!_.isObject(global.definition.paths)) { - require('../../utils/error.js')('paths is required') } let parameters = global.definition.paths[path][_.toLower(verb)]['parameters']; @@ -17,15 +16,24 @@ module.exports = function() { const result = [] _.forEach(queryParams, function(queryParam) { const param = queryParam.schema ? queryParam : getContentProperty(queryParam); - result.push({ + + const obj = { name: queryParam.name, type: param.schema.type, required : queryParam.required, - example: getExamples(param) - }); + }; + + const example = getExamples(param); + + if (example !== undefined && example !== null) { + obj.example = example; + } + + result.push(obj); }); + return result - }; + }; function replaceRefs(schema){ let result = {} @@ -58,15 +66,22 @@ module.exports = function() { } function getExamples(queryParam) { + if (!queryParam || !queryParam.schema) return undefined; + if (queryParam.schema.type === 'array') { - return queryParam.example - } else { - if (queryParam.hasOwnProperty('examples')) { - const value = queryParam.examples[Object.keys(queryParam.examples)[0]]; - return value[Object.keys(value)[0]]; + return queryParam.example; + } + + if (queryParam.hasOwnProperty('examples')) { + const firstKey = Object.keys(queryParam.examples)[0]; + const value = queryParam.examples[firstKey]; + if (value && value.hasOwnProperty('value')) { + return value.value; } - return queryParam.example; - } + return value; + } + + return queryParam.example !== undefined ? queryParam.example : queryParam.schema.example; } function getContentProperty(query){ diff --git a/src/parser/swagger2/body.js b/src/parser/swagger2/body.js index a28544d..856d3c7 100644 --- a/src/parser/swagger2/body.js +++ b/src/parser/swagger2/body.js @@ -8,8 +8,8 @@ module.exports = function() { let seenSchemas = new WeakSet(); - return function get(verb, path, bodyResponse) { + seenSchemas = new WeakSet(); if (!_.isObject(global.definition.paths)) { require('../../utils/error.js')('paths is required'); } @@ -106,6 +106,7 @@ module.exports = function() { } else if (k === 'required'){ merged['required'] = _.concat(merged['required'],schema[i][t]['required']); } else if (k === 'properties'){ + if (!merged['properties']) merged['properties'] = {}; for (let z in schema[i][t]['properties']){ merged['properties'][z] = replaceAllOfs(schema[i][t]['properties'][z]); } diff --git a/src/parser/swagger2/queryParams.js b/src/parser/swagger2/queryParams.js index 4620d90..54c565b 100644 --- a/src/parser/swagger2/queryParams.js +++ b/src/parser/swagger2/queryParams.js @@ -5,7 +5,7 @@ const _ = require('lodash'); module.exports = function() { - + return function get(verb,path){ if (!_.isObject(global.definition.paths)) { require('../../utils/error.js')('paths is required') @@ -15,17 +15,23 @@ module.exports = function() { // parameters = replaceRefs(parameters); const queryParams = _.filter(parameters, ['in', 'query']) const result = [] - _.forEach(queryParams, function(queryParam) { - result.push({ + _.forEach(queryParams, function(queryParam) { + const obj = { name : queryParam.name, type : queryParam.type, required : queryParam.required, - example: getExamples(queryParam) - }); - }) + }; + + const example = getExamples(queryParam); + if (example !== undefined && example !== null) { + obj.example = example; + } + + result.push(obj); + }); - return result - }; + return result; + }; function replaceRefs(schema){ let result = {}; @@ -57,18 +63,27 @@ module.exports = function() { } function getExamples(queryParam) { - if (queryParam.type === 'array') { - return queryParam.example; - } else { - if (queryParam.hasOwnProperty('examples')) { - const value = queryParam.examples[Object.keys(queryParam.examples)[0]]; - return value[Object.keys(value)[0]]; - } else if (queryParam.hasOwnProperty('default')) { - return queryParam.default; - } else { - return queryParam.example !== undefined ? queryParam.example : ''; + if (queryParam.hasOwnProperty('example')) { + return queryParam.example; + } + + if (queryParam.hasOwnProperty('x-example')) { + return queryParam['x-example']; + } + + if (queryParam.hasOwnProperty('default')) { + return queryParam.default; + } + + if (queryParam.hasOwnProperty('examples')) { + const examples = queryParam.examples; + const firstKey = Object.keys(examples)[0]; + if (typeof examples[firstKey] === 'object') { + return examples[firstKey][Object.keys(examples[firstKey])[0]]; } - } - } + return examples[firstKey]; + } + return undefined; + } }() \ No newline at end of file diff --git a/test/generator-endpoints.js b/test/generator-endpoints.js index bd8ac4d..3d57b59 100644 --- a/test/generator-endpoints.js +++ b/test/generator-endpoints.js @@ -3,7 +3,7 @@ const assert = require('assert'); describe('generator-endpoints', () => { - + it('good', () => { const definitionInitial = require('../seeds/generatorEndpointsInitial.json'); diff --git a/test/generator-examples.js b/test/generator-examples.js index 081f57f..93c5310 100644 --- a/test/generator-examples.js +++ b/test/generator-examples.js @@ -7,7 +7,7 @@ describe('generator-examples', () => { it('no examples', () => { global.definition = require('../seeds/generatorExamplesInitial.json') const examples = require('../src/generator/examples.js')('/user/{username}','get','400') - assert.strictEqual(examples, false); + assert.strictEqual(examples, null); }) // Check if the function returns an example when there are examples it('with examples', () => { diff --git a/test/generator-folders.js b/test/generator-folders.js index 034bde1..2f10b94 100644 --- a/test/generator-folders.js +++ b/test/generator-folders.js @@ -3,7 +3,7 @@ const assert = require('assert'); describe('generator-folders', () => { - + it('good', () => { const input = require('../seeds/generatorFoldersInitial.json') diff --git a/test/parser-body.js b/test/parser-body.js index e957752..e2f640e 100644 --- a/test/parser-body.js +++ b/test/parser-body.js @@ -3,7 +3,7 @@ const assert = require('assert') describe('parser-body', () => { - + it('void request swagger2', () => { global.definition = require('../seeds/parserInitialGood.json') diff --git a/test/parser-endpoints.js b/test/parser-endpoints.js index 3e51c2a..4d5d7a0 100644 --- a/test/parser-endpoints.js +++ b/test/parser-endpoints.js @@ -5,12 +5,16 @@ const sinon = require('sinon'); describe('parser-endpoints', () => { - before(() => { +before(() => { sinon.stub(process, 'exit'); + sinon.stub(console, 'log'); + sinon.stub(console, 'error'); }) after(() => { process.exit.restore(); + console.log.restore(); + console.error.restore(); }) it('bad swagger2', () => { From 1f3ac8d1ef292c90e56943dccbec0bb1512e3fd3 Mon Sep 17 00:00:00 2001 From: Melsy Huamani Date: Fri, 27 Feb 2026 16:46:13 -0500 Subject: [PATCH 3/8] feat: add openapi 3.1 compatibility --- package.json | 2 +- src/generator/examples.js | 6 +- src/parser/endpoints.js | 36 +-- src/parser/openapi31/body.js | 280 +++++++++++++++++++++ src/parser/openapi31/consumes.js | 25 ++ src/parser/openapi31/headers.js | 47 ++++ src/parser/openapi31/microcks.js | 15 ++ src/parser/openapi31/pathParameters.js | 28 +++ src/parser/openapi31/queryParams.js | 67 +++++ src/parser/openapi31/refs.js | 37 +++ src/parser/openapi31/schemaHostBasePath.js | 27 ++ src/parser/status.js | 34 +-- src/parser/summary.js | 30 ++- src/parser/version.js | 21 +- src/swagger2json/index.js | 57 +++-- 15 files changed, 635 insertions(+), 77 deletions(-) create mode 100644 src/parser/openapi31/body.js create mode 100644 src/parser/openapi31/consumes.js create mode 100644 src/parser/openapi31/headers.js create mode 100644 src/parser/openapi31/microcks.js create mode 100644 src/parser/openapi31/pathParameters.js create mode 100644 src/parser/openapi31/queryParams.js create mode 100644 src/parser/openapi31/refs.js create mode 100644 src/parser/openapi31/schemaHostBasePath.js diff --git a/package.json b/package.json index 7458a1f..9bc5297 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openapi2postman", - "version": "2.2.7", + "version": "2.3.0", "description": "openapi2postman", "bin": { "o2p": "index.js" diff --git a/src/generator/examples.js b/src/generator/examples.js index 917d839..b21ed34 100644 --- a/src/generator/examples.js +++ b/src/generator/examples.js @@ -4,7 +4,11 @@ const _ = require("lodash"); module.exports = (function () { return function get(path, method, status) { - if (!_.isObject(global.definition.paths)) { + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); + + if (!hasPaths) { + if (hasWebhooks) return null; require('../utils/error.js')('paths is required'); } diff --git a/src/parser/endpoints.js b/src/parser/endpoints.js index 3df216f..f58bc1c 100644 --- a/src/parser/endpoints.js +++ b/src/parser/endpoints.js @@ -4,23 +4,27 @@ const _ = require('lodash'); -module.exports = function() { - - return function get(){ - if (!_.isObject(global.definition.paths)) { - require('../utils/error.js')('paths is required'); - } +module.exports = function () { - const items = []; - _.forEach(global.definition.paths, function(pathInfo,path) { - _.forEach(pathInfo, function(verbInfo,verb) { - items.push({ - 'verb' : _.toUpper(verb), - 'path' : path - }); - }); - }); - return items; + return function get() { + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); + + if (!hasPaths) { + if (hasWebhooks) return []; + require('../utils/error.js')('paths is required'); + } + + const items = []; + _.forEach(global.definition.paths, function (pathInfo, path) { + _.forEach(pathInfo, function (verbInfo, verb) { + items.push({ + 'verb': _.toUpper(verb), + 'path': path + }); + }); + }); + return items; }; }() \ No newline at end of file diff --git a/src/parser/openapi31/body.js b/src/parser/openapi31/body.js new file mode 100644 index 0000000..d189059 --- /dev/null +++ b/src/parser/openapi31/body.js @@ -0,0 +1,280 @@ +/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ + +'use strict' + +const _ = require('lodash') + +module.exports = function () { + + const MAX_DEPTH_LEVEL = 20; + let seenSchemas = new WeakSet(); + + return function get(verb, path, bodyResponse) { + seenSchemas = new WeakSet(); + + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); + + if (!hasPaths) { + if (hasWebhooks) return bodyResponse ? {} : undefined; + require('../../utils/error.js')('paths is required'); + } + const endpoint = global.definition.paths[path][_.toLower(verb)] + if (!endpoint) return undefined; + + if (!bodyResponse) { + let body = endpoint['requestBody']; + if (!body) return undefined; + + if (body['$ref']) { + let componentType = body['$ref'].split('/')[2] + const ref = _.replace(body['$ref'], '#/components/' + componentType + '/', '') + body = global.definition.components[componentType][ref] + } + if (!body.content['application/json']) { + const contentsArray = Object.keys(body.content); + let schema = undefined; + let properContent = false; + let index = 0; + while (!properContent && index < contentsArray.length) { + const mediaType = body.content[contentsArray[index]]; + + if (!mediaType.schema) { + if (contentsArray[index] === 'application/octet-stream') { + return { + type: 'string', + format: 'binary' + }; + } + continue; + } + + const withoutRefs = replaceRefs(mediaType.schema, 1); + switch (contentsArray[index]) { + case 'application/x-www-form-urlencoded': + schema = replaceAllOfs(withoutRefs); + properContent = true; + break; + case 'multipart/form-data': + schema = replaceAllOfs(body.content[contentsArray[index]].schema); + properContent = true; + break; + default: + properContent = false; + break; + } + index++; + } + + if (!properContent && contentsArray.length > 0) { + const firstContentType = contentsArray[0]; + const mediaType = body.content[firstContentType]; + + if (mediaType && mediaType.schema) { + const withoutRefs = replaceRefs(mediaType.schema, 1); + return replaceAllOfs(withoutRefs); + } + } + + if (!properContent) console.warn('\x1b[33m%s\x1b[0m', `Warning: cannot create body due to unknown content type (Endpoint: ${verb} ${path})`); + return schema; + } + const withOutRefs = replaceRefs(body.content['application/json'].schema, 1); + return replaceAllOfs(withOutRefs); + } + const bodyResponses = {} + _.forEach(endpoint['responses'], function (response, status) { + if (response && response.content && response.content['application/json'] && response.content['application/json'].schema) { + const withOutRefs = replaceRefs(response.content['application/json'].schema, 1) + bodyResponses[status] = replaceAllOfs(withOutRefs) + if (bodyResponses[status].hasOwnProperty('required')) { + const requiredWtihoutDuplicates = bodyResponses[status].required.filter((value, index, arr) => { + return arr.indexOf(value) === index; + }); + bodyResponses[status].required = requiredWtihoutDuplicates; + } + } + }) + return bodyResponses + } + + function replaceRefs(schema, depthLevel) { + if (!_.isObject(schema)) { + return schema; + } + let result = {} + if (depthLevel < MAX_DEPTH_LEVEL) { + for (const i in schema) { + if (i === '$ref') { + let componentType = schema[i].split('/')[2] + const ref = _.replace(schema[i], '#/components/' + componentType + '/', '') + if (checkCircularReferences(ref, 3, 2) || checkCircularReferences(ref, 3, 3) || checkCircularReferences(ref, 3, 4)) { + return { + type: 'string', + description: 'Circular REF solved swagger2postman' + } + } + + let entity = global.definition.components[componentType][ref] + if (!entity) { + require('../../utils/error.js')('ref ' + ref + ' is not defined') + } + + entity = replaceRefs(entity, depthLevel + 1); + result = _.merge({}, result, entity) + } else if (_.isArray(schema[i]) && i !== 'required') { + const arrayResult = [] + if (i === 'example' || i === 'examples') { + result[i] = schema[i]; + continue; + } + for (const k in schema[i]) { + arrayResult.push(replaceRefs(schema[i][k], depthLevel + 1)) + } + result[i] = arrayResult + } else if (_.isObject(schema[i]) && i !== 'required') { + result[i] = replaceRefs(schema[i], depthLevel + 1); + } else { + result[i] = schema[i]; + } + } + } + return result + } + + function replaceAllOfs(schema) { + if (!_.isObject(schema)) return schema; + + if (seenSchemas.has(schema)) { + return { + type: "string", + description: "Circular schema avoided" + }; + } + seenSchemas.add(schema); + + let result = {} + + if (Array.isArray(schema.type)) { + const nonNullType = schema.type.find(t => t !== 'null'); + result.type = nonNullType || schema.type[0]; + } + + for (let i in schema) { + if (i === 'type' && Array.isArray(schema.type)) { + continue; + } + if (i === 'allOf' && _.isArray(schema[i])) { + let merged = { 'required': [], 'properties': {}, 'type': 'object' } + for (let t in schema[i]) { + + if (schema[i][t]['type'] === 'string') { + merged = schema[i][t] + } else { + + for (let k in schema[i][t]) { + if (k === 'type') { + merged['type'] = schema[i][t][k] + } else if (k === 'required') { + merged['required'] = _.concat(merged['required'], schema[i][t]['required']) + } else if (k === 'properties') { + for (let z in schema[i][t]['properties']) { + merged['properties'][z] = replaceAllOfs(schema[i][t]['properties'][z]) + } + } else if (k === 'allOf') { + let downSchema = replaceAllOfs(schema[k]) + if (downSchema['0']) { + downSchema = downSchema['0'] + } + merged['required'] = _.concat(merged['required'], downSchema['required']) + merged['properties'] = _.merge(merged['properties'], downSchema['properties']) + continue + } else if (k === 'description') { + continue + } else if (k === 'items') { + continue + } else { + console.warn('the property ' + k + ' of allOf is not implemented') + } + } + + } + + } + result = _.merge({}, result, merged) + } else if (_.isArray(schema[i]) && i !== 'required') { + if (schema[i].every(v => !_.isObject(v))) { + result[i] = [...schema[i]]; + } else { + result[i] = schema[i].map(item => replaceAllOfs(item)); + } + } else if (_.isObject(schema[i]) && i !== 'required') { + const value = replaceAllOfs(schema[i]); + + if (_.isPlainObject(value) && _.isPlainObject(result[i])) { + result[i] = _.merge({}, result[i], value); + } else { + result[i] = value; + } + } else { + result[i] = schema[i] + } + } + if (typeof result.exclusiveMinimum === 'number') { + result.minimum = result.exclusiveMinimum; + result.exclusiveMinimum = true; + } + + if (typeof result.exclusiveMaximum === 'number') { + result.maximum = result.exclusiveMaximum; + result.exclusiveMaximum = true; + } + + if (schema.contentEncoding) { + result.contentEncoding = schema.contentEncoding; + } + + if (schema.contentMediaType) { + result.contentMediaType = schema.contentMediaType; + } + return result + } + + function checkCircularReferences(reference, depthLevel, patternNumber) { + if (!global.circularTail) { + global.circularTail = [] + } + if (!global.circularTail[patternNumber]) { + global.circularTail[patternNumber] = [reference] + return false + } + if (global.circularTail[patternNumber].length < (depthLevel * patternNumber)) { + global.circularTail[patternNumber].push(reference) + return false + } + + const groups = _.chunk(global.circularTail[patternNumber], patternNumber) + global.circularTail[patternNumber].shift() + global.circularTail[patternNumber].push(reference) + + let areEquals = true + let lastArray = groups[0] + comparation: + for (let i = 1; i < groups.length; i++) { + for (let k in groups[i]) { + if (groups[i][k] !== groups[i - 1][k]) { + areEquals = false + break comparation + } + } + } + + if (areEquals) { + global.circularTail = [] + } + + return areEquals + + } + +}() \ No newline at end of file diff --git a/src/parser/openapi31/consumes.js b/src/parser/openapi31/consumes.js new file mode 100644 index 0000000..7345c13 --- /dev/null +++ b/src/parser/openapi31/consumes.js @@ -0,0 +1,25 @@ +/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ + +'use strict' + +const _ = require('lodash'); + +module.exports = function () { + + return function get(verb, path) { + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); + + if (!hasPaths) { + if (hasWebhooks) return 'application/json'; + require('../../utils/error.js')('paths is required'); + } + + const request = global.definition.paths[path][_.toLower(verb)] + if (request.requestBody && request.requestBody.content) { + return _.keys(request.requestBody.content)[0] + } + return 'application/json'; + }; + +}() \ No newline at end of file diff --git a/src/parser/openapi31/headers.js b/src/parser/openapi31/headers.js new file mode 100644 index 0000000..29c1d7f --- /dev/null +++ b/src/parser/openapi31/headers.js @@ -0,0 +1,47 @@ +/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ + +'use strict' + +const _ = require('lodash'); + +module.exports = function () { + + return function get(verb, path) { + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); + + if (!hasPaths) { + if (hasWebhooks) return []; + require('../../utils/error.js')('paths is required'); + } + + let parameters = global.definition.paths[path][_.toLower(verb)]['parameters']; + let headers = _.filter(parameters, ['in', 'header']) + const result = [] + _.forEach(headers, function (header) { + result.push({ + key: header.name, + type: header.schema.type, + required: header.required, + value: getExamples(header) + }); + }); + return result + }; + + function getExamples(header) { + if (header.example) return header.example; + + if (header.schema?.examples) { + return header.schema.examples[0]; + } + + if (header.examples) { + const firstKey = Object.keys(header.examples)[0]; + return header.examples[firstKey]?.value; + } + + return undefined; + } + +}() \ No newline at end of file diff --git a/src/parser/openapi31/microcks.js b/src/parser/openapi31/microcks.js new file mode 100644 index 0000000..85fe170 --- /dev/null +++ b/src/parser/openapi31/microcks.js @@ -0,0 +1,15 @@ +const _ = require('lodash'); + +module.exports = (function (verb, path) { + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); + + if (!hasPaths) { + if (hasWebhooks) return false; + require('../../utils/error.js')('paths is required'); + } + + const endpoint = global.definition.paths[path][_.toLower(verb)] + + return !!endpoint["x-microcks-operation"] +}) \ No newline at end of file diff --git a/src/parser/openapi31/pathParameters.js b/src/parser/openapi31/pathParameters.js new file mode 100644 index 0000000..f1f5fef --- /dev/null +++ b/src/parser/openapi31/pathParameters.js @@ -0,0 +1,28 @@ +/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ + +'use strict' + +const _ = require('lodash') + +module.exports = function () { + + return function get(verb, path) { + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); + + if (!hasPaths) { + if (hasWebhooks) return []; + require('../../utils/error.js')('paths is required'); + } + + const parameters = global.definition.paths[path][_.toLower(verb)]['parameters'] + const parametersPath = _.filter(parameters, ['in', 'path']) + const result = [] + _.forEach(parametersPath, function (parameterPath) { + result.push({ name: parameterPath.name, type: parameterPath.schema.type, example: parameterPath.schema.example || parameterPath.schema.examples?.[0] }) + }) + + return result + } + +}() \ No newline at end of file diff --git a/src/parser/openapi31/queryParams.js b/src/parser/openapi31/queryParams.js new file mode 100644 index 0000000..f58529d --- /dev/null +++ b/src/parser/openapi31/queryParams.js @@ -0,0 +1,67 @@ +/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ + +'use strict' + +const _ = require('lodash'); + +module.exports = function() { + + return function get(verb,path){ + if (!_.isObject(global.definition.paths)) { + } + + let parameters = global.definition.paths[path][_.toLower(verb)]['parameters']; + let queryParams = _.filter(parameters, ['in', 'query']) + const result = [] + _.forEach(queryParams, function(queryParam) { + const param = queryParam.schema ? queryParam : getContentProperty(queryParam); + + const obj = { + name: queryParam.name, + type: param.schema.type, + required : queryParam.required, + }; + + const example = getExamples(param); + + if (example !== undefined && example !== null) { + obj.example = example; + } + + result.push(obj); + }); + + return result + }; + + function getExamples(queryParam) { + if (!queryParam || !queryParam.schema) return undefined; + + if (queryParam.schema.type === 'array') { + return queryParam.example; + } + + if (queryParam.schema?.examples) { + return queryParam.schema.examples[0]; + } + + if (queryParam.hasOwnProperty('examples')) { + const firstKey = Object.keys(queryParam.examples)[0]; + const value = queryParam.examples[firstKey]; + if (value && value.hasOwnProperty('value')) { + return value.value; + } + return value; + } + + return queryParam.example !== undefined ? queryParam.example : queryParam.schema.example; + } + + function getContentProperty(query){ + const queryContent = query.content; + for (const key in queryContent) { + return queryContent[key]; + } + } + +}() \ No newline at end of file diff --git a/src/parser/openapi31/refs.js b/src/parser/openapi31/refs.js new file mode 100644 index 0000000..4f64218 --- /dev/null +++ b/src/parser/openapi31/refs.js @@ -0,0 +1,37 @@ +/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ + +'use strict' + +function eachRecursive(obj) { + for (var k in obj) { + if (typeof obj[k] == "object" && obj[k] !== null) { + eachRecursive(obj[k]); + } else { + if (k == '$ref') { + let property = obj[k] + property = property.replace('#/', '') + let propertiesArray = property.split('/') + let refObject = findObject(global.definition, propertiesArray) + delete obj[k] + + Object.assign(obj, refObject) + } + } + } +} + +function findObject(obj, propertiesArray) { + if(propertiesArray.length < 1) { + return obj + } + + let property = propertiesArray.shift() + return findObject(obj[property], propertiesArray) +} + +module.exports = function() { + return function get() { + eachRecursive(global.definition) + return global.definition + } +}() \ No newline at end of file diff --git a/src/parser/openapi31/schemaHostBasePath.js b/src/parser/openapi31/schemaHostBasePath.js new file mode 100644 index 0000000..14c693b --- /dev/null +++ b/src/parser/openapi31/schemaHostBasePath.js @@ -0,0 +1,27 @@ +/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ + +'use strict' + +const _ = require('lodash'); + +module.exports = function() { + + return function get(){ + if (!global.definition.servers || !_.isArray(global.definition.servers) || !global.definition.servers[0] || !global.definition.servers[0].url || !_.isString(global.definition.servers[0].url)) { + require('../../utils/error.js')('servers is required') + } + const all = global.definition.servers[0].url + const allArray = all.split( '/' ) + const protocol = allArray[0] + if (protocol !== 'http:' && protocol !== 'https:' && protocol !== '{scheme}:') { + require('../../utils/error.js')('servers.url should be http or https') + } + const domain = allArray[2] + const host = protocol + '//' + domain + return { + host: host, + basePath: all.replace(host, '') + }; + }; + +}() \ No newline at end of file diff --git a/src/parser/status.js b/src/parser/status.js index b3dcf86..093897e 100644 --- a/src/parser/status.js +++ b/src/parser/status.js @@ -4,22 +4,26 @@ const _ = require('lodash'); -module.exports = function() { - - return function get(verb,path){ - if (!_.isObject(global.definition.paths)) { - require('../../utils/error.js')('paths is required') - } +module.exports = function () { - const responses = global.definition.paths[path][_.toLower(verb)]['responses'] - const keys = _.keys(responses) - for (const index in keys) { - keys[index] = _.toInteger(keys[index]) - if (keys[index] < 200) { - keys[index] = 500 - } - } - return keys + return function get(verb, path) { + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); + + if (!hasPaths) { + if (hasWebhooks) return []; + require('../../utils/error.js')('paths is required'); + } + + const responses = global.definition.paths[path][_.toLower(verb)]['responses'] + const keys = _.keys(responses) + for (const index in keys) { + keys[index] = _.toInteger(keys[index]) + if (keys[index] < 200) { + keys[index] = 500 + } + } + return keys } }() \ No newline at end of file diff --git a/src/parser/summary.js b/src/parser/summary.js index 93294d3..49f9e81 100644 --- a/src/parser/summary.js +++ b/src/parser/summary.js @@ -4,19 +4,23 @@ const _ = require('lodash') -module.exports = function() { - - return function get(verb,path){ - if (!_.isObject(global.definition.paths)) { - require('../../utils/error.js')('paths is required') - } - - const endpoint = global.definition.paths[path][_.toLower(verb)] - if (_.has(endpoint,'summary')){ - return endpoint.summary - } - - return false +module.exports = function () { + + return function get(verb, path) { + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); + + if (!hasPaths) { + if (hasWebhooks) return false; + require('../../utils/error.js')('paths is required'); + } + + const endpoint = global.definition.paths[path][_.toLower(verb)] + if (_.has(endpoint, 'summary')) { + return endpoint.summary + } + + return false } }() \ No newline at end of file diff --git a/src/parser/version.js b/src/parser/version.js index 65945f2..eeb757e 100644 --- a/src/parser/version.js +++ b/src/parser/version.js @@ -5,16 +5,19 @@ module.exports = function() { return function get(){ - const versions = { - swagger : ['2.0', '2.0.0'], - openapi : ['3.0', '3.0.0', '3.0.1','3.0.2', '3.0.3', '3.1.0', '3.1.1', '3.1.2'] - } + const versions = { + swagger : ['2.0', '2.0.0'], + openapi3 : ['3.0', '3.0.0', '3.0.1','3.0.2', '3.0.3'], + openapi31 : ['3.1', '3.1.0', '3.1.1', '3.1.2'] + } - if (versions.swagger.includes(global.definition.swagger)) { - return 'swagger2' - } else if (versions.openapi.includes(global.definition.openapi)){ - return 'openapi3' - } + if (versions.swagger.includes(global.definition.swagger)) { + return 'swagger2' + } else if (versions.openapi3.includes(global.definition.openapi)) { + return 'openapi3' + } else if (versions.openapi31.includes(global.definition.openapi)) { + return 'openapi31' + } require('../utils/error.js')('Specification is not supported') }; diff --git a/src/swagger2json/index.js b/src/swagger2json/index.js index 5d2e630..fa5d62b 100644 --- a/src/swagger2json/index.js +++ b/src/swagger2json/index.js @@ -4,12 +4,25 @@ const _ = require('lodash'); -module.exports = function() { - - return function get(swagger, name, parent,index){ -if (typeof swagger !== 'object' || swagger === null) { - swagger = { type: 'string' }; - } +module.exports = function () { + + return function get(swagger, name, parent, index) { + if (Array.isArray(swagger.type)) { + + swagger.type = swagger.type.map(t => { + if (typeof t === 'object' && !Array.isArray(t)) { + return Object.values(t).join('') + } + return t + }) + + const nonNullTypes = swagger.type.filter(t => t !== 'null'); + swagger.type = nonNullTypes[0] || 'string'; + } + + if (typeof swagger !== 'object' || swagger === null) { + swagger = { type: 'string' }; + } if (!swagger.type) { if (swagger.properties) { @@ -36,30 +49,30 @@ if (typeof swagger !== 'object' || swagger === null) { case 'object': if (wrongParam) { - global.environmentVariables[global.currentId+name+'_wrong'] = require('../utils/exampleForField.js')(swagger,true) - return '{{'+name+'_wrong}}' + global.environmentVariables[global.currentId + name + '_wrong'] = require('../utils/exampleForField.js')(swagger, true) + return '{{' + name + '_wrong}}' } - - return require('./object.js')(swagger,parent) + + return require('./object.js')(swagger, parent) case 'array': if (wrongParam) { - global.environmentVariables[global.currentId+name+'_wrong'] = require('../utils/exampleForField.js')(swagger,true) - return '{{'+name+'_wrong}}' + global.environmentVariables[global.currentId + name + '_wrong'] = require('../utils/exampleForField.js')(swagger, true) + return '{{' + name + '_wrong}}' } - - return require('./array.js')(swagger,name,parent); + + return require('./array.js')(swagger, name, parent); case 'string': case 'number': case 'integer': case 'boolean': - + if (wrongParam) { - global.environmentVariables[global.currentId+name+'_wrong'] = require('../utils/exampleForField.js')(swagger,true) - return '{{'+name+'_wrong}}' + global.environmentVariables[global.currentId + name + '_wrong'] = require('../utils/exampleForField.js')(swagger, true) + return '{{' + name + '_wrong}}' } - global.environmentVariables[global.currentId+name] = require('../utils/exampleForField.js')(swagger,false) - return '{{'+name+'}}' + global.environmentVariables[global.currentId + name] = require('../utils/exampleForField.js')(swagger, false) + return '{{' + name + '}}' case 'oneOf': let schemaOne = swagger.oneOf[index]; return anyOfOneOfChoice(schemaOne, name, parent); @@ -67,7 +80,7 @@ if (typeof swagger !== 'object' || swagger === null) { let schemaAny = swagger.anyOf[index]; return anyOfOneOfChoice(schemaAny, name, parent); default: - require('../utils/error.js')('The type '+swagger.type+' is not implemented'); + require('../utils/error.js')('The type ' + swagger.type + ' is not implemented'); } } @@ -78,8 +91,8 @@ if (typeof swagger !== 'object' || swagger === null) { case 'array': return require('./array.js')(schema, name, parent); default: - global.environmentVariables[global.currentId+name] = require('../utils/exampleForField.js')(schema, false); - return '{{'+name+'}}'; + global.environmentVariables[global.currentId + name] = require('../utils/exampleForField.js')(schema, false); + return '{{' + name + '}}'; } } From aa20b529f83458af8767a2e6878206debd32ffbe Mon Sep 17 00:00:00 2001 From: Melsy Huamani Date: Fri, 27 Feb 2026 19:15:24 -0500 Subject: [PATCH 4/8] feat: extend test suite to support openapi 3.1 --- .../parserAuthorizationInitialOpenApi3.1.json | 290 ++++++++++++++++++ seeds/parserInitialGoodOpenApi3.1.1.json | 178 +++++++++++ seeds/parserInitialGoodOpenApi3.1.2.json | 178 +++++++++++ seeds/parserInitialGoodOpenApi3.1.json | 178 +++++++++++ .../parserInitialGoodOpenApiExpanded3.1.json | 214 +++++++++++++ ...=> parserInitialGoodOpenApiExpanded3.json} | 0 seeds/parserMicroksinitialGood3.1.json | 117 +++++++ ...od.json => parserMicroksinitialGood3.json} | 0 seeds/parserSummaryOpenApi3.1.json | 117 +++++++ test/parser-authorization.js | 17 +- test/parser-body.js | 49 ++- test/parser-consumes.js | 24 +- test/parser-endpoints.js | 14 +- test/parser-microcks.js | 25 +- test/parser-pathParameters.js | 10 +- test/parser-queryParams.js | 32 +- test/parser-schemaHostBasePath.js | 12 +- test/parser-status.js | 12 +- test/parser-summary.js | 10 +- test/parser-version.js | 38 ++- 20 files changed, 1469 insertions(+), 46 deletions(-) create mode 100644 seeds/parserAuthorizationInitialOpenApi3.1.json create mode 100644 seeds/parserInitialGoodOpenApi3.1.1.json create mode 100644 seeds/parserInitialGoodOpenApi3.1.2.json create mode 100644 seeds/parserInitialGoodOpenApi3.1.json create mode 100644 seeds/parserInitialGoodOpenApiExpanded3.1.json rename seeds/{parserInitialGoodOpenApi3Expanded.json => parserInitialGoodOpenApiExpanded3.json} (100%) create mode 100644 seeds/parserMicroksinitialGood3.1.json rename seeds/{parserMicroksinitialGood.json => parserMicroksinitialGood3.json} (100%) create mode 100644 seeds/parserSummaryOpenApi3.1.json diff --git a/seeds/parserAuthorizationInitialOpenApi3.1.json b/seeds/parserAuthorizationInitialOpenApi3.1.json new file mode 100644 index 0000000..0c56c67 --- /dev/null +++ b/seeds/parserAuthorizationInitialOpenApi3.1.json @@ -0,0 +1,290 @@ +{ + "openapi": "3.1.0", + "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema", + "info": { + "version": "1.0.0", + "title": "Swagger Petstore", + "description": "A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.1 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" + } + }, + "servers": [ + { + "url": "http://petstore.swagger.io/api" + } + ], + "security": [ + { + "ApiKeyAuth": [] + } + ], + "paths": { + "/pets": { + "get": { + "security": [ + { + "OAuth2": ["admin"] + } + ], + "description": "Returns all pets from the system that the user has access to", + "operationId": "findPets", + "parameters": [ + { + "name": "tags", + "in": "query", + "description": "tags to filter by", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "limit", + "in": "query", + "description": "maximum number of results to return", + "required": false, + "schema": { + "type": ["integer", "null"], + "format": "int32", + "minimum": 1 + } + } + ], + "responses": { + "200": { + "description": "pet response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "default": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "post": { + "description": "Creates a new pet in the store. Duplicates are allowed", + "operationId": "addPet", + "requestBody": { + "description": "Pet to add to the store", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "200": { + "description": "pet response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "default": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/pets/{id}": { + "get": { + "description": "Returns a pet based on a single ID", + "operationId": "findPetById", + "parameters": [ + { + "$ref": "#/components/parameters/PetId" + } + ], + "responses": { + "200": { + "description": "pet response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "pet not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "delete": { + "description": "Deletes a single pet based on the ID supplied", + "operationId": "deletePet", + "parameters": [ + { + "$ref": "#/components/parameters/PetId" + } + ], + "responses": { + "204": { + "description": "pet deleted" + }, + "default": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + } + }, + "components": { + "parameters": { + "PetId": { + "name": "id", + "in": "path", + "description": "ID of pet", + "required": true, + "schema": { + "type": "integer", + "format": "int64", + "minimum": 1 + } + } + }, + "securitySchemes": { + "BasicAuth": { + "type": "http", + "scheme": "basic" + }, + "BearerAuth": { + "type": "http", + "scheme": "bearer" + }, + "ApiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "X-API-Key" + }, + "OpenID": { + "type": "openIdConnect", + "openIdConnectUrl": "https://example.com/.well-known/openid-configuration" + }, + "OAuth2": { + "type": "oauth2", + "flows": { + "authorizationCode": { + "authorizationUrl": "https://example.com/oauth/authorize", + "tokenUrl": "https://example.com/oauth/token", + "scopes": { + "read": "Grants read access", + "write": "Grants write access", + "admin": "Grants access to admin operations" + } + } + } + } + }, + "schemas": { + "Pet": { + "allOf": [ + { + "$ref": "#/components/schemas/NewPet" + }, + { + "type": "object", + "required": ["id"], + "properties": { + "id": { + "type": "integer", + "format": "int64" + } + }, + "unevaluatedProperties": false + } + ] + }, + "NewPet": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "tag": { + "type": ["string", "null"], + "examples": ["dog", "cat", null] + }, + "status": { + "type": "string", + "const": "available" + } + }, + "unevaluatedProperties": false + }, + "Error": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "required": ["code", "message"], + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + } + }, + "unevaluatedProperties": false + } + } + } +} \ No newline at end of file diff --git a/seeds/parserInitialGoodOpenApi3.1.1.json b/seeds/parserInitialGoodOpenApi3.1.1.json new file mode 100644 index 0000000..0df0a71 --- /dev/null +++ b/seeds/parserInitialGoodOpenApi3.1.1.json @@ -0,0 +1,178 @@ +{ + "openapi":"3.1.2", + "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" + } + } + ], + "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":"Create a pet", + "operationId":"createPets", + "tags":[ + "pets" + ], + "responses":{ + "201":{ + "description":"Null response" + }, + "default":{ + "description":"unexpected error", + "content":{ + "application/json":{ + "schema":{ + "$ref":"#/components/schemas/Error" + } + } + } + } + } + } + }, + "/pets/{petId}":{ + "get":{ + "summary":"Info for a specific pet", + "operationId":"showPetById", + "tags":[ + "pets" + ], + "parameters":[ + { + "name":"petId", + "in":"path", + "required":true, + "description":"The id of the pet to retrieve", + "schema":{ + "type":"string", + "example":"asdf" + } + } + ], + "responses":{ + "200":{ + "description":"Expected response to a valid request", + "content":{ + "application/json":{ + "schema":{ + "$ref":"#/components/schemas/Pet" + } + } + } + }, + "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/seeds/parserInitialGoodOpenApi3.1.2.json b/seeds/parserInitialGoodOpenApi3.1.2.json new file mode 100644 index 0000000..58b4511 --- /dev/null +++ b/seeds/parserInitialGoodOpenApi3.1.2.json @@ -0,0 +1,178 @@ +{ + "openapi":"3.1.1", + "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" + } + } + ], + "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":"Create a pet", + "operationId":"createPets", + "tags":[ + "pets" + ], + "responses":{ + "201":{ + "description":"Null response" + }, + "default":{ + "description":"unexpected error", + "content":{ + "application/json":{ + "schema":{ + "$ref":"#/components/schemas/Error" + } + } + } + } + } + } + }, + "/pets/{petId}":{ + "get":{ + "summary":"Info for a specific pet", + "operationId":"showPetById", + "tags":[ + "pets" + ], + "parameters":[ + { + "name":"petId", + "in":"path", + "required":true, + "description":"The id of the pet to retrieve", + "schema":{ + "type":"string", + "example":"asdf" + } + } + ], + "responses":{ + "200":{ + "description":"Expected response to a valid request", + "content":{ + "application/json":{ + "schema":{ + "$ref":"#/components/schemas/Pet" + } + } + } + }, + "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/seeds/parserInitialGoodOpenApi3.1.json b/seeds/parserInitialGoodOpenApi3.1.json new file mode 100644 index 0000000..03e9bd5 --- /dev/null +++ b/seeds/parserInitialGoodOpenApi3.1.json @@ -0,0 +1,178 @@ +{ + "openapi":"3.1.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" + } + } + ], + "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":"Create a pet", + "operationId":"createPets", + "tags":[ + "pets" + ], + "responses":{ + "201":{ + "description":"Null response" + }, + "default":{ + "description":"unexpected error", + "content":{ + "application/json":{ + "schema":{ + "$ref":"#/components/schemas/Error" + } + } + } + } + } + } + }, + "/pets/{petId}":{ + "get":{ + "summary":"Info for a specific pet", + "operationId":"showPetById", + "tags":[ + "pets" + ], + "parameters":[ + { + "name":"petId", + "in":"path", + "required":true, + "description":"The id of the pet to retrieve", + "schema":{ + "type":"string", + "example":"asdf" + } + } + ], + "responses":{ + "200":{ + "description":"Expected response to a valid request", + "content":{ + "application/json":{ + "schema":{ + "$ref":"#/components/schemas/Pet" + } + } + } + }, + "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/seeds/parserInitialGoodOpenApiExpanded3.1.json b/seeds/parserInitialGoodOpenApiExpanded3.1.json new file mode 100644 index 0000000..31e4567 --- /dev/null +++ b/seeds/parserInitialGoodOpenApiExpanded3.1.json @@ -0,0 +1,214 @@ +{ + "openapi": "3.1.0", + "info": { + "version": "1.0.0", + "title": "Swagger Petstore" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/api" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "findPets", + "parameters": [ + { + "name": "tags", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "limit", + "in": "query", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "pet response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "500": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "200": { + "description": "pet response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "500": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/pets/{id}": { + "get": { + "operationId": "findPetById", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "pet response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "500": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "delete": { + "operationId": "deletePet", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "204": { + "description": "pet deleted" + }, + "500": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "allOf": [ + { + "$ref": "#/components/schemas/NewPet" + }, + { + "type": "object", + "required": ["id"], + "properties": { + "id": { + "type": "integer", + "format": "int64" + } + } + } + ] + }, + "NewPet": { + "type": "object", + "required": ["name"], + "properties": { + "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/seeds/parserInitialGoodOpenApi3Expanded.json b/seeds/parserInitialGoodOpenApiExpanded3.json similarity index 100% rename from seeds/parserInitialGoodOpenApi3Expanded.json rename to seeds/parserInitialGoodOpenApiExpanded3.json diff --git a/seeds/parserMicroksinitialGood3.1.json b/seeds/parserMicroksinitialGood3.1.json new file mode 100644 index 0000000..1abbcdb --- /dev/null +++ b/seeds/parserMicroksinitialGood3.1.json @@ -0,0 +1,117 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Swagger Petstore 2.0", + "description": "This is a sample server Petstore server.", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "email": "apiteam@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.0" + }, + "servers": [ + { + "url": "https://petstore.swagger.io/v2" + }, + { + "url": "http://petstore.swagger.io/v2" + } + ], + "paths": { + "/user": { + "post": { + "tags": ["user"], + "summary": "Create user", + "operationId": "createUser", + "requestBody": { + "required": true, + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/{username}": { + "get": { + "tags": ["user"], + "summary": "Get user by user name", + "operationId": "getUserByName", + "parameters": [ + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + } + }, + "x-microcks-operation": { + "delay": 100, + "dispatcher": "SCRIPT", + "dispatcherRules": "def headers = mockRequest.getRequestHeaders(); if (headers.hasValues(\"X-Microcks-Response-Name\")) { return headers.get(\"X-Microcks-Response-Name\", \"null\") }" + } + } + } + }, + "components": { + "schemas": { + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "username": { + "type": "string" + }, + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "userStatus": { + "type": "integer", + "format": "int32" + } + } + } + } + } +} \ No newline at end of file diff --git a/seeds/parserMicroksinitialGood.json b/seeds/parserMicroksinitialGood3.json similarity index 100% rename from seeds/parserMicroksinitialGood.json rename to seeds/parserMicroksinitialGood3.json diff --git a/seeds/parserSummaryOpenApi3.1.json b/seeds/parserSummaryOpenApi3.1.json new file mode 100644 index 0000000..93a9397 --- /dev/null +++ b/seeds/parserSummaryOpenApi3.1.json @@ -0,0 +1,117 @@ +{ + "openapi": "3.1.0", + "jsonSchemaDialect": "https://spec.openapis.org/oas/3.1/dialect/base", + "info": { + "version": "1.0.0", + "title": "Swagger Petstore", + "description": "A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.1 specification", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "name": "Swagger API Team", + "email": "apiteam@swagger.io", + "url": "http://swagger.io" + }, + "license": { + "name": "Apache 2.0", + "identifier": "Apache-2.0" + } + }, + "servers": [ + { + "url": "http://petstore.swagger.io/api" + } + ], + "security": [ + { + "ApiKeyAuth": [] + } + ], + "paths": { + "/pets": { + "get": { + "summary": "Pets list", + "operationId": "findPets", + "responses": { + "200": { + "description": "pet response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "summary": "Create pet", + "operationId": "addPet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "200": { + "description": "pet response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "ApiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "X-API-Key" + } + }, + "schemas": { + "Pet": { + "allOf": [ + { + "$ref": "#/components/schemas/NewPet" + }, + { + "type": "object", + "required": ["id"], + "properties": { + "id": { + "type": "integer" + } + } + } + ] + }, + "NewPet": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": ["string", "null"] + } + } + } + } + } +} \ No newline at end of file diff --git a/test/parser-authorization.js b/test/parser-authorization.js index 1e3ca96..da80df7 100644 --- a/test/parser-authorization.js +++ b/test/parser-authorization.js @@ -25,18 +25,31 @@ describe('parser-authorization', () => { assert.deepStrictEqual(authorization, 'BasicAuth') }) - it('general openapi3', () => { + it('general openapi3.0', () => { global.definition = require('../seeds/parserAuthorizationInitialOpenApi3.json') const authorization = require('../src/parser/authorization.js')('POST','/pets') assert.deepStrictEqual(authorization, 'ApiKeyAuth') }) - it('endpoint openapi3', () => { + it('endpoint openapi3.0', () => { global.definition = require('../seeds/parserAuthorizationInitialOpenApi3.json') const authorization = require('../src/parser/authorization.js')('GET','/pets') assert.deepStrictEqual(authorization, 'OAuth2') }) + it('general openapi3.1', () => { + + global.definition = require('../seeds/parserAuthorizationInitialOpenApi3.1.json') + const authorization = require('../src/parser/authorization.js')('POST','/pets') + assert.deepStrictEqual(authorization, 'ApiKeyAuth') + }) + + it('endpoint openapi3.1', () => { + + global.definition = require('../seeds/parserAuthorizationInitialOpenApi3.1.json') + const authorization = require('../src/parser/authorization.js')('GET','/pets') + assert.deepStrictEqual(authorization, 'OAuth2') + }) }) \ No newline at end of file diff --git a/test/parser-body.js b/test/parser-body.js index e2f640e..01e6d92 100644 --- a/test/parser-body.js +++ b/test/parser-body.js @@ -12,7 +12,7 @@ describe('parser-body', () => { assert.deepStrictEqual(body, undefined) }) - it('void request openapi3', () => { + it('void request openapi3.0', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.json') @@ -20,7 +20,7 @@ describe('parser-body', () => { assert.deepStrictEqual(body, undefined) }) - it('void request openapi3 2', () => { + it('void request openapi3.0 2', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.json') @@ -28,6 +28,14 @@ describe('parser-body', () => { assert.deepStrictEqual(body, undefined) }) + it('void request openapi3.1', () => { + + global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') + + const body = require('../src/parser/openapi31/body.js')('GET','/pets') + assert.deepStrictEqual(body, undefined) + }) + it('fill request swagger2', () => { global.definition = require('../seeds/parserInitialGood.json') @@ -36,14 +44,22 @@ describe('parser-body', () => { assert.deepStrictEqual(body, {"type":"object","required":["name"],"properties":{"name":{"type":"string"},"tag":{"type":"string"}}}) }) - it('fill request openapi3', () => { + it('fill request openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3Expanded.json') + global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') const body = require('../src/parser/openapi3/body.js')('POST','/pets') assert.deepStrictEqual(body, {"type":"object","required":["name"],"properties":{"name":{"type":"string"},"tag":{"type":"string"}}}) }) + it('fill request openapi3.1', () => { + + global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') + + const body = require('../src/parser/openapi31/body.js')('POST','/pets') + assert.deepStrictEqual(body, {"type":"object","required":["name"],"properties":{"name":{"type":"string"},"tag":{"type":"string"}}}) + }) + it('items, ref and allof response swagger2', () => { global.definition = require('../seeds/parserInitialGood.json') @@ -52,14 +68,22 @@ describe('parser-body', () => { assert.deepStrictEqual(body, {"200":{"type":"array","items":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) }) - it('items, ref and allof response openapi3', () => { + it('items, ref and allof response openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3Expanded.json') + global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') const body = require('../src/parser/openapi3/body.js')('GET','/pets',true) assert.deepStrictEqual(body, {"200":{"type":"array","items":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) }) + it('items, ref and allof response openapi3.1', () => { + + global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') + + const body = require('../src/parser/openapi31/body.js')('GET','/pets',true) + assert.deepStrictEqual(body, {"200":{"type":"array","items":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) + }) + it('ref and allof response swagger2', () => { global.definition = require('../seeds/parserInitialGood.json') @@ -69,15 +93,24 @@ describe('parser-body', () => { assert.deepStrictEqual(body, {"200":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) }) - it('ref and allof response openapi3', () => { + it('ref and allof response openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3Expanded.json') + global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') global.circularTail = [] const body = require('../src/parser/openapi3/body.js')('POST','/pets',true) assert.deepStrictEqual(body, {"200":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) }) + it('ref and allof response openapi3.1', () => { + + global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') + global.circularTail = [] + + const body = require('../src/parser/openapi31/body.js')('POST','/pets',true) + assert.deepStrictEqual(body, {"200":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) + }) + it('allof loop swagger2', () => { global.definition = require('../seeds/parserBodyAllofLoopInitial.json') diff --git a/test/parser-consumes.js b/test/parser-consumes.js index 77cf001..3287804 100644 --- a/test/parser-consumes.js +++ b/test/parser-consumes.js @@ -3,7 +3,15 @@ const assert = require('assert') describe('parser-consumes', () => { - + + it('general swagger2', () => { + + global.definition = require('../seeds/parserConsumesInitial.json') + + const consumes = require('../src/parser/swagger2/consumes.js')('POST','/pets/{id}') + assert.equal(consumes, 'application/json') + }) + it('specifies swagger2', () => { global.definition = require('../seeds/parserConsumesInitial.json') @@ -12,19 +20,19 @@ describe('parser-consumes', () => { assert.equal(consumes, 'application/xml') }) - it('general swagger2', () => { + it('specifies openapi3.0', () => { - global.definition = require('../seeds/parserConsumesInitial.json') + global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json'); - const consumes = require('../src/parser/swagger2/consumes.js')('POST','/pets/{id}') - assert.equal(consumes, 'application/json') + const consumes = require('../src/parser/openapi3/consumes.js')('POST','/pets'); + assert.equal(consumes, 'application/json'); }) - it('specifies openapi3', () => { + it('specifies openapi3.1', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3Expanded.json'); + global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json'); - const consumes = require('../src/parser/openapi3/consumes.js')('POST','/pets'); + const consumes = require('../src/parser/openapi31/consumes.js')('POST','/pets'); assert.equal(consumes, 'application/json'); }) diff --git a/test/parser-endpoints.js b/test/parser-endpoints.js index 4d5d7a0..8945b59 100644 --- a/test/parser-endpoints.js +++ b/test/parser-endpoints.js @@ -40,7 +40,7 @@ before(() => { ]) }) - it('good openapi3', () => { + it('good openapi3.0', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.json'); @@ -53,4 +53,16 @@ before(() => { }) + it('good openapi3.1', () => { + + global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json'); + + const endpoints = require('../src/parser/endpoints.js')(); + assert.deepEqual(endpoints, [ + { verb: 'GET', path: '/pets' }, + { verb: 'POST', path: '/pets' }, + { verb: 'GET', path: '/pets/{petId}' } + ]) + }) + }) \ No newline at end of file diff --git a/test/parser-microcks.js b/test/parser-microcks.js index 0c72556..04ed2e3 100644 --- a/test/parser-microcks.js +++ b/test/parser-microcks.js @@ -3,34 +3,39 @@ const assert = require('assert') describe('parser-microcks', () => { - + //If the document is not openapi3, it should return false because it is not supported it('specifies swagger2', () => { - + global.definition = require('../seeds/parserMicroksInitial.json') - + const microcks = require('../src/parser/openapi3/microcks.js')('POST','/user') assert.equal(microcks, false) }) //If the document is not openapi3, it should return false because it is not supported it('general swagger2', () => { - + global.definition = require('../seeds/parserMicroksInitial.json') - + const microcks = require('../src/parser/openapi3/microcks.js')('GET','/user/{username}') assert.equal(microcks, false) }) //If the document is openapi3, it should return true because it is supported - it('specifies openapi3', () => { - - global.definition = require('../seeds/parserMicroksinitialGood.json'); - + it('specifies openapi3.0', () => { + + global.definition = require('../seeds/parserMicroksinitialGood3.json'); + const microcks = require('../src/parser/openapi3/microcks.js')('GET','/user/{username}'); assert.equal(microcks, true); }) - + it('specifies openapi3.1', () => { + + global.definition = require('../seeds/parserMicroksinitialGood3.1.json'); + const microcks = require('../src/parser/openapi31/microcks.js')('GET','/user/{username}'); + assert.equal(microcks, true); + }) }) diff --git a/test/parser-pathParameters.js b/test/parser-pathParameters.js index 6415713..1b33214 100644 --- a/test/parser-pathParameters.js +++ b/test/parser-pathParameters.js @@ -12,7 +12,7 @@ describe('parser-pathParameters', () => { assert.deepStrictEqual(pathParameters, [ { name: 'id', type: 'integer', example: undefined } ]) }) - it('good openapi3', () => { + it('good openapi3.0', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.json') @@ -20,4 +20,12 @@ describe('parser-pathParameters', () => { assert.deepStrictEqual(status, [ { name: 'petId', type: 'string', example: 'asdf' } ]) }) + it('good openapi3.1', () => { + + global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') + + const status = require('../src/parser/openapi31/pathParameters.js')('GET','/pets/{petId}') + assert.deepStrictEqual(status, [ { name: 'petId', type: 'string', example: 'asdf' } ]) + }) + }) \ No newline at end of file diff --git a/test/parser-queryParams.js b/test/parser-queryParams.js index 3806fb4..231974e 100644 --- a/test/parser-queryParams.js +++ b/test/parser-queryParams.js @@ -29,9 +29,9 @@ describe('parser-queryParams', () => { assert.deepStrictEqual(queryParams, []) }) - it('fill openapi3', () => { + it('fill openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3Expanded.json') + global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') const queryParams = require('../src/parser/openapi3/queryParams.js')('GET','/pets') assert.deepStrictEqual(queryParams, [{ @@ -46,12 +46,36 @@ describe('parser-queryParams', () => { } ]) }) - it('void openapi3', () => { + it('void openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3Expanded.json') + global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') const queryParams = require('../src/parser/openapi3/queryParams.js')('POST','/pets') assert.deepStrictEqual(queryParams, []) }) + it('fill openapi3.1', () => { + + global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') + + const queryParams = require('../src/parser/openapi31/queryParams.js')('GET','/pets') + assert.deepStrictEqual(queryParams, [{ + "name": "tags", + "required": false, + "type": "array" + }, + { + "name": "limit", + "required": true, + "type": "integer" + } ]) + }) + + it('void openapi3.1', () => { + + global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') + + const queryParams = require('../src/parser/openapi31/queryParams.js')('POST','/pets') + assert.deepStrictEqual(queryParams, []) + }) }) \ No newline at end of file diff --git a/test/parser-schemaHostBasePath.js b/test/parser-schemaHostBasePath.js index 55d283c..167914f 100644 --- a/test/parser-schemaHostBasePath.js +++ b/test/parser-schemaHostBasePath.js @@ -3,7 +3,7 @@ const assert = require('assert'); describe('parser-schemaHostBasePath', () => { - + it('good swagger2', () => { global.definition = require('../seeds/parserSchemaHostBasePathInitialGood.json'); @@ -12,11 +12,19 @@ describe('parser-schemaHostBasePath', () => { assert.deepStrictEqual(schemaHostBasePath, { host: 'https://myserver.com', basePath: '/first/second' }); }) - it('good openapi3', () => { + it('good openapi3.0', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.json'); const schemaHostBasePath = require('../src/parser/openapi3/schemaHostBasePath.js')(); assert.deepStrictEqual(schemaHostBasePath, { host: 'http://petstore.swagger.io', basePath: '/v1' }); }) + + it('good openapi3.1', () => { + + global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json'); + + const schemaHostBasePath = require('../src/parser/openapi31/schemaHostBasePath.js')(); + assert.deepStrictEqual(schemaHostBasePath, { host: 'http://petstore.swagger.io', basePath: '/v1' }); + }) }); \ No newline at end of file diff --git a/test/parser-status.js b/test/parser-status.js index b0d83c4..17563d2 100644 --- a/test/parser-status.js +++ b/test/parser-status.js @@ -3,7 +3,7 @@ const assert = require('assert'); describe('parser-status', () => { - + it('good swagger2', () => { global.definition = require('../seeds/parserInitialGood.json') @@ -12,7 +12,7 @@ describe('parser-status', () => { assert.deepStrictEqual(status, [ 204, 500 ]) }) - it('good openapi3', () => { + it('good openapi3.0', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.json') @@ -20,4 +20,12 @@ describe('parser-status', () => { assert.deepStrictEqual(status, [ 201, 500 ]) }) + it('good openapi3.1', () => { + + global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') + + const status = require('../src/parser/status.js')('POST','/pets') + assert.deepStrictEqual(status, [ 201, 500 ]) + }) + }); \ No newline at end of file diff --git a/test/parser-summary.js b/test/parser-summary.js index f8b1211..e6eac16 100644 --- a/test/parser-summary.js +++ b/test/parser-summary.js @@ -12,7 +12,7 @@ describe('parser-summary', () => { assert.equal(summary, "Create a pet") }) - it('good swagger2', () => { + it('good openapi3.0', () => { global.definition = require('../seeds/parserSummaryOpenApi3.json') @@ -20,4 +20,12 @@ describe('parser-summary', () => { assert.equal(summary, "Create pet") }) + it('good openapi3.1', () => { + + global.definition = require('../seeds/parserSummaryOpenApi3.1.json') + + const summary = require('../src/parser/summary.js')('POST','/pets') + assert.equal(summary, "Create pet") + }) + }) \ No newline at end of file diff --git a/test/parser-version.js b/test/parser-version.js index a240676..a6e3990 100644 --- a/test/parser-version.js +++ b/test/parser-version.js @@ -12,7 +12,7 @@ describe('parser-version', () => { assert.equal(version, 'swagger2') }); - it('openapi3', () => { + it('openapi3.0', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.json') @@ -20,19 +20,43 @@ describe('parser-version', () => { assert.equal(version, 'openapi3') }); - it('openapi versio 3.0.2' , () => { - + it('openapi version 3.0.2' , () => { + global.definition = require('../seeds/parserInitialGoodOpenApi3.0.2.json') - + const version = require('../src/parser/version.js')() assert.equal(version, 'openapi3') }) - it('openapi versio 3.0.3' , () => { - + it('openapi version 3.0.3' , () => { + global.definition = require('../seeds/parserInitialGoodOpenApi3.0.3.json') - + const version = require('../src/parser/version.js')() assert.equal(version, 'openapi3') }) + + it('openapi3.1', () => { + + global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') + + const version = require('../src/parser/version.js')() + assert.equal(version, 'openapi31') + }); + + it('openapi version 3.1.1' , () => { + + global.definition = require('../seeds/parserInitialGoodOpenApi3.1.1.json') + + const version = require('../src/parser/version.js')() + assert.equal(version, 'openapi31') + }) + + it('openapi version 3.1.2' , () => { + + global.definition = require('../seeds/parserInitialGoodOpenApi3.1.2.json') + + const version = require('../src/parser/version.js')() + assert.equal(version, 'openapi31') + }) }); \ No newline at end of file From e7a61384e9cf6bbcc373c9b6aeb36bdb51c5b1e4 Mon Sep 17 00:00:00 2001 From: Melsy Huamani Date: Mon, 2 Mar 2026 09:49:14 -0500 Subject: [PATCH 5/8] fix: sonarqube issues and duplications --- seeds/parserInitialGoodOpenApi3.1.json | 2 +- src/parser/openapi3/body.js | 156 ++++++++---- src/parser/openapi3/consumes.js | 26 +- src/parser/openapi3/headers.js | 49 ++-- src/parser/openapi3/microcks.js | 16 +- src/parser/openapi3/pathParameters.js | 30 ++- src/parser/openapi3/queryParams.js | 4 + src/parser/openapi3/schemaHostBasePath.js | 2 +- src/parser/openapi31/body.js | 280 --------------------- src/parser/openapi31/consumes.js | 25 -- src/parser/openapi31/headers.js | 47 ---- src/parser/openapi31/microcks.js | 15 -- src/parser/openapi31/pathParameters.js | 28 --- src/parser/openapi31/queryParams.js | 67 ----- src/parser/openapi31/refs.js | 37 --- src/parser/openapi31/schemaHostBasePath.js | 27 -- src/parser/version.js | 7 +- test/parser-authorization.js | 14 +- test/parser-body.js | 38 +-- test/parser-consumes.js | 2 +- test/parser-endpoints.js | 8 +- test/parser-microcks.js | 2 +- test/parser-pathParameters.js | 2 +- test/parser-queryParams.js | 16 +- test/parser-schemaHostBasePath.js | 4 +- test/parser-version.js | 6 +- 26 files changed, 232 insertions(+), 678 deletions(-) delete mode 100644 src/parser/openapi31/body.js delete mode 100644 src/parser/openapi31/consumes.js delete mode 100644 src/parser/openapi31/headers.js delete mode 100644 src/parser/openapi31/microcks.js delete mode 100644 src/parser/openapi31/pathParameters.js delete mode 100644 src/parser/openapi31/queryParams.js delete mode 100644 src/parser/openapi31/refs.js delete mode 100644 src/parser/openapi31/schemaHostBasePath.js diff --git a/seeds/parserInitialGoodOpenApi3.1.json b/seeds/parserInitialGoodOpenApi3.1.json index 03e9bd5..325ee25 100644 --- a/seeds/parserInitialGoodOpenApi3.1.json +++ b/seeds/parserInitialGoodOpenApi3.1.json @@ -9,7 +9,7 @@ }, "servers":[ { - "url":"http://petstore.swagger.io/v1" + "url":"https://petstore.swagger.io/v1" } ], "paths":{ diff --git a/src/parser/openapi3/body.js b/src/parser/openapi3/body.js index 13fc51e..d189059 100644 --- a/src/parser/openapi3/body.js +++ b/src/parser/openapi3/body.js @@ -4,7 +4,7 @@ const _ = require('lodash') -module.exports = function() { +module.exports = function () { const MAX_DEPTH_LEVEL = 20; let seenSchemas = new WeakSet(); @@ -12,19 +12,23 @@ module.exports = function() { return function get(verb, path, bodyResponse) { seenSchemas = new WeakSet(); - if (!_.isObject(global.definition.paths)) { - require('../../utils/error.js')('paths is required') + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); + + if (!hasPaths) { + if (hasWebhooks) return bodyResponse ? {} : undefined; + require('../../utils/error.js')('paths is required'); } const endpoint = global.definition.paths[path][_.toLower(verb)] if (!endpoint) return undefined; - if (!bodyResponse){ + if (!bodyResponse) { let body = endpoint['requestBody']; if (!body) return undefined; if (body['$ref']) { let componentType = body['$ref'].split('/')[2] - const ref = _.replace(body['$ref'], '#/components/'+componentType+'/', '') + const ref = _.replace(body['$ref'], '#/components/' + componentType + '/', '') body = global.definition.components[componentType][ref] } if (!body.content['application/json']) { @@ -32,10 +36,21 @@ module.exports = function() { let schema = undefined; let properContent = false; let index = 0; - // Búsqueda de un content type soportado por la aplicación while (!properContent && index < contentsArray.length) { - const withoutRefs = replaceRefs(body.content[contentsArray[index]].schema, 1); - switch(contentsArray[index]) { + const mediaType = body.content[contentsArray[index]]; + + if (!mediaType.schema) { + if (contentsArray[index] === 'application/octet-stream') { + return { + type: 'string', + format: 'binary' + }; + } + continue; + } + + const withoutRefs = replaceRefs(mediaType.schema, 1); + switch (contentsArray[index]) { case 'application/x-www-form-urlencoded': schema = replaceAllOfs(withoutRefs); properContent = true; @@ -51,6 +66,16 @@ module.exports = function() { index++; } + if (!properContent && contentsArray.length > 0) { + const firstContentType = contentsArray[0]; + const mediaType = body.content[firstContentType]; + + if (mediaType && mediaType.schema) { + const withoutRefs = replaceRefs(mediaType.schema, 1); + return replaceAllOfs(withoutRefs); + } + } + if (!properContent) console.warn('\x1b[33m%s\x1b[0m', `Warning: cannot create body due to unknown content type (Endpoint: ${verb} ${path})`); return schema; } @@ -58,7 +83,7 @@ module.exports = function() { return replaceAllOfs(withOutRefs); } const bodyResponses = {} - _.forEach(endpoint['responses'], function(response, status) { + _.forEach(endpoint['responses'], function (response, status) { if (response && response.content && response.content['application/json'] && response.content['application/json'].schema) { const withOutRefs = replaceRefs(response.content['application/json'].schema, 1) bodyResponses[status] = replaceAllOfs(withOutRefs) @@ -66,7 +91,7 @@ module.exports = function() { const requiredWtihoutDuplicates = bodyResponses[status].required.filter((value, index, arr) => { return arr.indexOf(value) === index; }); - bodyResponses[status].required = requiredWtihoutDuplicates; + bodyResponses[status].required = requiredWtihoutDuplicates; } } }) @@ -74,35 +99,40 @@ module.exports = function() { } function replaceRefs(schema, depthLevel) { + if (!_.isObject(schema)) { + return schema; + } let result = {} if (depthLevel < MAX_DEPTH_LEVEL) { for (const i in schema) { if (i === '$ref') { let componentType = schema[i].split('/')[2] - const ref = _.replace(schema[i], '#/components/'+componentType+'/', '') - if (checkCircularReferences(ref,3,2) || checkCircularReferences(ref,3,3) || checkCircularReferences(ref,3,4)){ - return { type: 'string', - description: 'Circular REF solved swagger2postman' + const ref = _.replace(schema[i], '#/components/' + componentType + '/', '') + if (checkCircularReferences(ref, 3, 2) || checkCircularReferences(ref, 3, 3) || checkCircularReferences(ref, 3, 4)) { + return { + type: 'string', + description: 'Circular REF solved swagger2postman' } } let entity = global.definition.components[componentType][ref] if (!entity) { - require('../../utils/error.js')('ref '+ref+' is not defined') + require('../../utils/error.js')('ref ' + ref + ' is not defined') } entity = replaceRefs(entity, depthLevel + 1); - result = _.merge(result, entity) - } else if ( _.isArray(schema[i]) && i !== 'required') { + result = _.merge({}, result, entity) + } else if (_.isArray(schema[i]) && i !== 'required') { const arrayResult = [] - if (i === 'example'){ - continue + if (i === 'example' || i === 'examples') { + result[i] = schema[i]; + continue; } for (const k in schema[i]) { arrayResult.push(replaceRefs(schema[i][k], depthLevel + 1)) } result[i] = arrayResult - } else if ( _.isObject(schema[i]) && i !== 'required') { + } else if (_.isObject(schema[i]) && i !== 'required') { result[i] = replaceRefs(schema[i], depthLevel + 1); } else { result[i] = schema[i]; @@ -112,10 +142,9 @@ module.exports = function() { return result } - function replaceAllOfs(schema){ + function replaceAllOfs(schema) { if (!_.isObject(schema)) return schema; - // Detectar ciclos por identidad if (seenSchemas.has(schema)) { return { type: "string", @@ -125,70 +154,101 @@ module.exports = function() { seenSchemas.add(schema); let result = {} + + if (Array.isArray(schema.type)) { + const nonNullType = schema.type.find(t => t !== 'null'); + result.type = nonNullType || schema.type[0]; + } + for (let i in schema) { - if (i === 'allOf' && _.isArray(schema[i])){ - let merged = {'required':[],'properties':{},'type':'object'} + if (i === 'type' && Array.isArray(schema.type)) { + continue; + } + if (i === 'allOf' && _.isArray(schema[i])) { + let merged = { 'required': [], 'properties': {}, 'type': 'object' } for (let t in schema[i]) { if (schema[i][t]['type'] === 'string') { merged = schema[i][t] } else { - + for (let k in schema[i][t]) { - if (k === 'type'){ + if (k === 'type') { merged['type'] = schema[i][t][k] - } else if (k === 'required'){ - merged['required'] = _.concat(merged['required'],schema[i][t]['required']) - } else if (k === 'properties'){ - for (let z in schema[i][t]['properties']){ + } else if (k === 'required') { + merged['required'] = _.concat(merged['required'], schema[i][t]['required']) + } else if (k === 'properties') { + for (let z in schema[i][t]['properties']) { merged['properties'][z] = replaceAllOfs(schema[i][t]['properties'][z]) } - } else if (k === 'allOf'){ + } else if (k === 'allOf') { let downSchema = replaceAllOfs(schema[k]) if (downSchema['0']) { downSchema = downSchema['0'] } - merged['required'] = _.concat(merged['required'],downSchema['required']) - merged['properties'] = _.merge(merged['properties'],downSchema['properties']) + merged['required'] = _.concat(merged['required'], downSchema['required']) + merged['properties'] = _.merge(merged['properties'], downSchema['properties']) continue } else if (k === 'description') { continue } else if (k === 'items') { continue - }else { - console.warn('the property '+k+' of allOf is not implemented') + } else { + console.warn('the property ' + k + ' of allOf is not implemented') } } } } - result = _.merge(result, merged) - } else if ( _.isArray(schema[i]) && i !== 'required') { + result = _.merge({}, result, merged) + } else if (_.isArray(schema[i]) && i !== 'required') { if (schema[i].every(v => !_.isObject(v))) { result[i] = [...schema[i]]; } else { result[i] = schema[i].map(item => replaceAllOfs(item)); } - } else if ( _.isObject(schema[i]) && i !== 'required') { - // result.type = 'object'; - result[i] = _.merge(result[i],replaceAllOfs(schema[i])) + } else if (_.isObject(schema[i]) && i !== 'required') { + const value = replaceAllOfs(schema[i]); + + if (_.isPlainObject(value) && _.isPlainObject(result[i])) { + result[i] = _.merge({}, result[i], value); + } else { + result[i] = value; + } } else { result[i] = schema[i] } } + if (typeof result.exclusiveMinimum === 'number') { + result.minimum = result.exclusiveMinimum; + result.exclusiveMinimum = true; + } + + if (typeof result.exclusiveMaximum === 'number') { + result.maximum = result.exclusiveMaximum; + result.exclusiveMaximum = true; + } + + if (schema.contentEncoding) { + result.contentEncoding = schema.contentEncoding; + } + + if (schema.contentMediaType) { + result.contentMediaType = schema.contentMediaType; + } return result } - - function checkCircularReferences(reference,depthLevel,patternNumber){ - if (!global.circularTail){ + + function checkCircularReferences(reference, depthLevel, patternNumber) { + if (!global.circularTail) { global.circularTail = [] } - if (! global.circularTail[patternNumber] ){ + if (!global.circularTail[patternNumber]) { global.circularTail[patternNumber] = [reference] return false } - if (global.circularTail[patternNumber].length < (depthLevel * patternNumber) ){ + if (global.circularTail[patternNumber].length < (depthLevel * patternNumber)) { global.circularTail[patternNumber].push(reference) return false } @@ -201,15 +261,15 @@ module.exports = function() { let lastArray = groups[0] comparation: for (let i = 1; i < groups.length; i++) { - for (let k in groups[i]){ - if (groups[i][k] !== groups[i - 1][k]){ + for (let k in groups[i]) { + if (groups[i][k] !== groups[i - 1][k]) { areEquals = false break comparation } } } - if (areEquals){ + if (areEquals) { global.circularTail = [] } diff --git a/src/parser/openapi3/consumes.js b/src/parser/openapi3/consumes.js index 854257d..7345c13 100644 --- a/src/parser/openapi3/consumes.js +++ b/src/parser/openapi3/consumes.js @@ -4,18 +4,22 @@ const _ = require('lodash'); -module.exports = function() { - - return function get(verb,path){ - if (!_.isObject(global.definition.paths)) { - require('../../utils/error.js')('paths is required'); - } +module.exports = function () { - const request = global.definition.paths[path][_.toLower(verb)] - if (request.requestBody && request.requestBody.content){ - return _.keys(request.requestBody.content)[0] - } - return 'application/json'; + return function get(verb, path) { + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); + + if (!hasPaths) { + if (hasWebhooks) return 'application/json'; + require('../../utils/error.js')('paths is required'); + } + + const request = global.definition.paths[path][_.toLower(verb)] + if (request.requestBody && request.requestBody.content) { + return _.keys(request.requestBody.content)[0] + } + return 'application/json'; }; }() \ No newline at end of file diff --git a/src/parser/openapi3/headers.js b/src/parser/openapi3/headers.js index f810947..29c1d7f 100644 --- a/src/parser/openapi3/headers.js +++ b/src/parser/openapi3/headers.js @@ -4,22 +4,25 @@ const _ = require('lodash'); -module.exports = function() { - - return function get(verb,path){ - if (!_.isObject(global.definition.paths)) { - require('../../utils/error.js')('paths is required') +module.exports = function () { + + return function get(verb, path) { + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); + + if (!hasPaths) { + if (hasWebhooks) return []; + require('../../utils/error.js')('paths is required'); } let parameters = global.definition.paths[path][_.toLower(verb)]['parameters']; - // parameters = replaceRefs(parameters); let headers = _.filter(parameters, ['in', 'header']) const result = [] - _.forEach(headers, function(header) { - result.push({ - key: header.name, - type: header.schema.type, - required : header.required, + _.forEach(headers, function (header) { + result.push({ + key: header.name, + type: header.schema.type, + required: header.required, value: getExamples(header) }); }); @@ -27,16 +30,18 @@ module.exports = function() { }; function getExamples(header) { - if (header.example) { - return header.example - } - else { - if (header.hasOwnProperty('examples')) { - const value = header.examples[Object.keys(header.examples)[0]]; - return value[Object.keys(value)[0]]; - } - return header.example; - } - } + if (header.example) return header.example; + + if (header.schema?.examples) { + return header.schema.examples[0]; + } + + if (header.examples) { + const firstKey = Object.keys(header.examples)[0]; + return header.examples[firstKey]?.value; + } + + return undefined; + } }() \ No newline at end of file diff --git a/src/parser/openapi3/microcks.js b/src/parser/openapi3/microcks.js index eb55082..f4644c5 100644 --- a/src/parser/openapi3/microcks.js +++ b/src/parser/openapi3/microcks.js @@ -1,11 +1,15 @@ const _ = require('lodash'); module.exports = (function (verb, path) { - if (!_.isObject(global.definition.paths)) { - require('../../utils/error.js')('paths is required'); - } + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); - const endpoint = global.definition.paths[path][_.toLower(verb)] - - return !!endpoint["x-microcks-operation"] + if (!hasPaths) { + if (hasWebhooks) return false; + require('../../utils/error.js')('paths is required'); + } + + const endpoint = global.definition.paths[path][_.toLower(verb)] + + return !!endpoint["x-microcks-operation"] }) \ No newline at end of file diff --git a/src/parser/openapi3/pathParameters.js b/src/parser/openapi3/pathParameters.js index d74bd1c..f1f5fef 100644 --- a/src/parser/openapi3/pathParameters.js +++ b/src/parser/openapi3/pathParameters.js @@ -4,21 +4,25 @@ const _ = require('lodash') -module.exports = function() { - - return function get(verb,path){ - if (!_.isObject(global.definition.paths)) { - require('../../utils/error.js')('paths is required') - } - - const parameters = global.definition.paths[path][_.toLower(verb)]['parameters'] - const parametersPath = _.filter(parameters, ['in', 'path']) +module.exports = function () { + + return function get(verb, path) { + const hasPaths = _.isObject(global.definition.paths); + const hasWebhooks = _.isObject(global.definition.webhooks); + + if (!hasPaths) { + if (hasWebhooks) return []; + require('../../utils/error.js')('paths is required'); + } + + const parameters = global.definition.paths[path][_.toLower(verb)]['parameters'] + const parametersPath = _.filter(parameters, ['in', 'path']) const result = [] - _.forEach(parametersPath, function(parameterPath) { - result.push( { name : parameterPath.name , type: parameterPath.schema.type, example: parameterPath.schema.example} ) - }) + _.forEach(parametersPath, function (parameterPath) { + result.push({ name: parameterPath.name, type: parameterPath.schema.type, example: parameterPath.schema.example || parameterPath.schema.examples?.[0] }) + }) - return result + return result } }() \ No newline at end of file diff --git a/src/parser/openapi3/queryParams.js b/src/parser/openapi3/queryParams.js index 59f2922..0e0145f 100644 --- a/src/parser/openapi3/queryParams.js +++ b/src/parser/openapi3/queryParams.js @@ -72,6 +72,10 @@ module.exports = function() { return queryParam.example; } + if (queryParam.schema?.examples) { + return queryParam.schema.examples[0]; + } + if (queryParam.hasOwnProperty('examples')) { const firstKey = Object.keys(queryParam.examples)[0]; const value = queryParam.examples[firstKey]; diff --git a/src/parser/openapi3/schemaHostBasePath.js b/src/parser/openapi3/schemaHostBasePath.js index fe1fe6e..14c693b 100644 --- a/src/parser/openapi3/schemaHostBasePath.js +++ b/src/parser/openapi3/schemaHostBasePath.js @@ -5,7 +5,7 @@ const _ = require('lodash'); module.exports = function() { - + return function get(){ if (!global.definition.servers || !_.isArray(global.definition.servers) || !global.definition.servers[0] || !global.definition.servers[0].url || !_.isString(global.definition.servers[0].url)) { require('../../utils/error.js')('servers is required') diff --git a/src/parser/openapi31/body.js b/src/parser/openapi31/body.js deleted file mode 100644 index d189059..0000000 --- a/src/parser/openapi31/body.js +++ /dev/null @@ -1,280 +0,0 @@ -/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ - -'use strict' - -const _ = require('lodash') - -module.exports = function () { - - const MAX_DEPTH_LEVEL = 20; - let seenSchemas = new WeakSet(); - - return function get(verb, path, bodyResponse) { - seenSchemas = new WeakSet(); - - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); - - if (!hasPaths) { - if (hasWebhooks) return bodyResponse ? {} : undefined; - require('../../utils/error.js')('paths is required'); - } - const endpoint = global.definition.paths[path][_.toLower(verb)] - if (!endpoint) return undefined; - - if (!bodyResponse) { - let body = endpoint['requestBody']; - if (!body) return undefined; - - if (body['$ref']) { - let componentType = body['$ref'].split('/')[2] - const ref = _.replace(body['$ref'], '#/components/' + componentType + '/', '') - body = global.definition.components[componentType][ref] - } - if (!body.content['application/json']) { - const contentsArray = Object.keys(body.content); - let schema = undefined; - let properContent = false; - let index = 0; - while (!properContent && index < contentsArray.length) { - const mediaType = body.content[contentsArray[index]]; - - if (!mediaType.schema) { - if (contentsArray[index] === 'application/octet-stream') { - return { - type: 'string', - format: 'binary' - }; - } - continue; - } - - const withoutRefs = replaceRefs(mediaType.schema, 1); - switch (contentsArray[index]) { - case 'application/x-www-form-urlencoded': - schema = replaceAllOfs(withoutRefs); - properContent = true; - break; - case 'multipart/form-data': - schema = replaceAllOfs(body.content[contentsArray[index]].schema); - properContent = true; - break; - default: - properContent = false; - break; - } - index++; - } - - if (!properContent && contentsArray.length > 0) { - const firstContentType = contentsArray[0]; - const mediaType = body.content[firstContentType]; - - if (mediaType && mediaType.schema) { - const withoutRefs = replaceRefs(mediaType.schema, 1); - return replaceAllOfs(withoutRefs); - } - } - - if (!properContent) console.warn('\x1b[33m%s\x1b[0m', `Warning: cannot create body due to unknown content type (Endpoint: ${verb} ${path})`); - return schema; - } - const withOutRefs = replaceRefs(body.content['application/json'].schema, 1); - return replaceAllOfs(withOutRefs); - } - const bodyResponses = {} - _.forEach(endpoint['responses'], function (response, status) { - if (response && response.content && response.content['application/json'] && response.content['application/json'].schema) { - const withOutRefs = replaceRefs(response.content['application/json'].schema, 1) - bodyResponses[status] = replaceAllOfs(withOutRefs) - if (bodyResponses[status].hasOwnProperty('required')) { - const requiredWtihoutDuplicates = bodyResponses[status].required.filter((value, index, arr) => { - return arr.indexOf(value) === index; - }); - bodyResponses[status].required = requiredWtihoutDuplicates; - } - } - }) - return bodyResponses - } - - function replaceRefs(schema, depthLevel) { - if (!_.isObject(schema)) { - return schema; - } - let result = {} - if (depthLevel < MAX_DEPTH_LEVEL) { - for (const i in schema) { - if (i === '$ref') { - let componentType = schema[i].split('/')[2] - const ref = _.replace(schema[i], '#/components/' + componentType + '/', '') - if (checkCircularReferences(ref, 3, 2) || checkCircularReferences(ref, 3, 3) || checkCircularReferences(ref, 3, 4)) { - return { - type: 'string', - description: 'Circular REF solved swagger2postman' - } - } - - let entity = global.definition.components[componentType][ref] - if (!entity) { - require('../../utils/error.js')('ref ' + ref + ' is not defined') - } - - entity = replaceRefs(entity, depthLevel + 1); - result = _.merge({}, result, entity) - } else if (_.isArray(schema[i]) && i !== 'required') { - const arrayResult = [] - if (i === 'example' || i === 'examples') { - result[i] = schema[i]; - continue; - } - for (const k in schema[i]) { - arrayResult.push(replaceRefs(schema[i][k], depthLevel + 1)) - } - result[i] = arrayResult - } else if (_.isObject(schema[i]) && i !== 'required') { - result[i] = replaceRefs(schema[i], depthLevel + 1); - } else { - result[i] = schema[i]; - } - } - } - return result - } - - function replaceAllOfs(schema) { - if (!_.isObject(schema)) return schema; - - if (seenSchemas.has(schema)) { - return { - type: "string", - description: "Circular schema avoided" - }; - } - seenSchemas.add(schema); - - let result = {} - - if (Array.isArray(schema.type)) { - const nonNullType = schema.type.find(t => t !== 'null'); - result.type = nonNullType || schema.type[0]; - } - - for (let i in schema) { - if (i === 'type' && Array.isArray(schema.type)) { - continue; - } - if (i === 'allOf' && _.isArray(schema[i])) { - let merged = { 'required': [], 'properties': {}, 'type': 'object' } - for (let t in schema[i]) { - - if (schema[i][t]['type'] === 'string') { - merged = schema[i][t] - } else { - - for (let k in schema[i][t]) { - if (k === 'type') { - merged['type'] = schema[i][t][k] - } else if (k === 'required') { - merged['required'] = _.concat(merged['required'], schema[i][t]['required']) - } else if (k === 'properties') { - for (let z in schema[i][t]['properties']) { - merged['properties'][z] = replaceAllOfs(schema[i][t]['properties'][z]) - } - } else if (k === 'allOf') { - let downSchema = replaceAllOfs(schema[k]) - if (downSchema['0']) { - downSchema = downSchema['0'] - } - merged['required'] = _.concat(merged['required'], downSchema['required']) - merged['properties'] = _.merge(merged['properties'], downSchema['properties']) - continue - } else if (k === 'description') { - continue - } else if (k === 'items') { - continue - } else { - console.warn('the property ' + k + ' of allOf is not implemented') - } - } - - } - - } - result = _.merge({}, result, merged) - } else if (_.isArray(schema[i]) && i !== 'required') { - if (schema[i].every(v => !_.isObject(v))) { - result[i] = [...schema[i]]; - } else { - result[i] = schema[i].map(item => replaceAllOfs(item)); - } - } else if (_.isObject(schema[i]) && i !== 'required') { - const value = replaceAllOfs(schema[i]); - - if (_.isPlainObject(value) && _.isPlainObject(result[i])) { - result[i] = _.merge({}, result[i], value); - } else { - result[i] = value; - } - } else { - result[i] = schema[i] - } - } - if (typeof result.exclusiveMinimum === 'number') { - result.minimum = result.exclusiveMinimum; - result.exclusiveMinimum = true; - } - - if (typeof result.exclusiveMaximum === 'number') { - result.maximum = result.exclusiveMaximum; - result.exclusiveMaximum = true; - } - - if (schema.contentEncoding) { - result.contentEncoding = schema.contentEncoding; - } - - if (schema.contentMediaType) { - result.contentMediaType = schema.contentMediaType; - } - return result - } - - function checkCircularReferences(reference, depthLevel, patternNumber) { - if (!global.circularTail) { - global.circularTail = [] - } - if (!global.circularTail[patternNumber]) { - global.circularTail[patternNumber] = [reference] - return false - } - if (global.circularTail[patternNumber].length < (depthLevel * patternNumber)) { - global.circularTail[patternNumber].push(reference) - return false - } - - const groups = _.chunk(global.circularTail[patternNumber], patternNumber) - global.circularTail[patternNumber].shift() - global.circularTail[patternNumber].push(reference) - - let areEquals = true - let lastArray = groups[0] - comparation: - for (let i = 1; i < groups.length; i++) { - for (let k in groups[i]) { - if (groups[i][k] !== groups[i - 1][k]) { - areEquals = false - break comparation - } - } - } - - if (areEquals) { - global.circularTail = [] - } - - return areEquals - - } - -}() \ No newline at end of file diff --git a/src/parser/openapi31/consumes.js b/src/parser/openapi31/consumes.js deleted file mode 100644 index 7345c13..0000000 --- a/src/parser/openapi31/consumes.js +++ /dev/null @@ -1,25 +0,0 @@ -/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ - -'use strict' - -const _ = require('lodash'); - -module.exports = function () { - - return function get(verb, path) { - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); - - if (!hasPaths) { - if (hasWebhooks) return 'application/json'; - require('../../utils/error.js')('paths is required'); - } - - const request = global.definition.paths[path][_.toLower(verb)] - if (request.requestBody && request.requestBody.content) { - return _.keys(request.requestBody.content)[0] - } - return 'application/json'; - }; - -}() \ No newline at end of file diff --git a/src/parser/openapi31/headers.js b/src/parser/openapi31/headers.js deleted file mode 100644 index 29c1d7f..0000000 --- a/src/parser/openapi31/headers.js +++ /dev/null @@ -1,47 +0,0 @@ -/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ - -'use strict' - -const _ = require('lodash'); - -module.exports = function () { - - return function get(verb, path) { - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); - - if (!hasPaths) { - if (hasWebhooks) return []; - require('../../utils/error.js')('paths is required'); - } - - let parameters = global.definition.paths[path][_.toLower(verb)]['parameters']; - let headers = _.filter(parameters, ['in', 'header']) - const result = [] - _.forEach(headers, function (header) { - result.push({ - key: header.name, - type: header.schema.type, - required: header.required, - value: getExamples(header) - }); - }); - return result - }; - - function getExamples(header) { - if (header.example) return header.example; - - if (header.schema?.examples) { - return header.schema.examples[0]; - } - - if (header.examples) { - const firstKey = Object.keys(header.examples)[0]; - return header.examples[firstKey]?.value; - } - - return undefined; - } - -}() \ No newline at end of file diff --git a/src/parser/openapi31/microcks.js b/src/parser/openapi31/microcks.js deleted file mode 100644 index 85fe170..0000000 --- a/src/parser/openapi31/microcks.js +++ /dev/null @@ -1,15 +0,0 @@ -const _ = require('lodash'); - -module.exports = (function (verb, path) { - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); - - if (!hasPaths) { - if (hasWebhooks) return false; - require('../../utils/error.js')('paths is required'); - } - - const endpoint = global.definition.paths[path][_.toLower(verb)] - - return !!endpoint["x-microcks-operation"] -}) \ No newline at end of file diff --git a/src/parser/openapi31/pathParameters.js b/src/parser/openapi31/pathParameters.js deleted file mode 100644 index f1f5fef..0000000 --- a/src/parser/openapi31/pathParameters.js +++ /dev/null @@ -1,28 +0,0 @@ -/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ - -'use strict' - -const _ = require('lodash') - -module.exports = function () { - - return function get(verb, path) { - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); - - if (!hasPaths) { - if (hasWebhooks) return []; - require('../../utils/error.js')('paths is required'); - } - - const parameters = global.definition.paths[path][_.toLower(verb)]['parameters'] - const parametersPath = _.filter(parameters, ['in', 'path']) - const result = [] - _.forEach(parametersPath, function (parameterPath) { - result.push({ name: parameterPath.name, type: parameterPath.schema.type, example: parameterPath.schema.example || parameterPath.schema.examples?.[0] }) - }) - - return result - } - -}() \ No newline at end of file diff --git a/src/parser/openapi31/queryParams.js b/src/parser/openapi31/queryParams.js deleted file mode 100644 index f58529d..0000000 --- a/src/parser/openapi31/queryParams.js +++ /dev/null @@ -1,67 +0,0 @@ -/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ - -'use strict' - -const _ = require('lodash'); - -module.exports = function() { - - return function get(verb,path){ - if (!_.isObject(global.definition.paths)) { - } - - let parameters = global.definition.paths[path][_.toLower(verb)]['parameters']; - let queryParams = _.filter(parameters, ['in', 'query']) - const result = [] - _.forEach(queryParams, function(queryParam) { - const param = queryParam.schema ? queryParam : getContentProperty(queryParam); - - const obj = { - name: queryParam.name, - type: param.schema.type, - required : queryParam.required, - }; - - const example = getExamples(param); - - if (example !== undefined && example !== null) { - obj.example = example; - } - - result.push(obj); - }); - - return result - }; - - function getExamples(queryParam) { - if (!queryParam || !queryParam.schema) return undefined; - - if (queryParam.schema.type === 'array') { - return queryParam.example; - } - - if (queryParam.schema?.examples) { - return queryParam.schema.examples[0]; - } - - if (queryParam.hasOwnProperty('examples')) { - const firstKey = Object.keys(queryParam.examples)[0]; - const value = queryParam.examples[firstKey]; - if (value && value.hasOwnProperty('value')) { - return value.value; - } - return value; - } - - return queryParam.example !== undefined ? queryParam.example : queryParam.schema.example; - } - - function getContentProperty(query){ - const queryContent = query.content; - for (const key in queryContent) { - return queryContent[key]; - } - } - -}() \ No newline at end of file diff --git a/src/parser/openapi31/refs.js b/src/parser/openapi31/refs.js deleted file mode 100644 index 4f64218..0000000 --- a/src/parser/openapi31/refs.js +++ /dev/null @@ -1,37 +0,0 @@ -/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ - -'use strict' - -function eachRecursive(obj) { - for (var k in obj) { - if (typeof obj[k] == "object" && obj[k] !== null) { - eachRecursive(obj[k]); - } else { - if (k == '$ref') { - let property = obj[k] - property = property.replace('#/', '') - let propertiesArray = property.split('/') - let refObject = findObject(global.definition, propertiesArray) - delete obj[k] - - Object.assign(obj, refObject) - } - } - } -} - -function findObject(obj, propertiesArray) { - if(propertiesArray.length < 1) { - return obj - } - - let property = propertiesArray.shift() - return findObject(obj[property], propertiesArray) -} - -module.exports = function() { - return function get() { - eachRecursive(global.definition) - return global.definition - } -}() \ No newline at end of file diff --git a/src/parser/openapi31/schemaHostBasePath.js b/src/parser/openapi31/schemaHostBasePath.js deleted file mode 100644 index 14c693b..0000000 --- a/src/parser/openapi31/schemaHostBasePath.js +++ /dev/null @@ -1,27 +0,0 @@ -/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ - -'use strict' - -const _ = require('lodash'); - -module.exports = function() { - - return function get(){ - if (!global.definition.servers || !_.isArray(global.definition.servers) || !global.definition.servers[0] || !global.definition.servers[0].url || !_.isString(global.definition.servers[0].url)) { - require('../../utils/error.js')('servers is required') - } - const all = global.definition.servers[0].url - const allArray = all.split( '/' ) - const protocol = allArray[0] - if (protocol !== 'http:' && protocol !== 'https:' && protocol !== '{scheme}:') { - require('../../utils/error.js')('servers.url should be http or https') - } - const domain = allArray[2] - const host = protocol + '//' + domain - return { - host: host, - basePath: all.replace(host, '') - }; - }; - -}() \ No newline at end of file diff --git a/src/parser/version.js b/src/parser/version.js index eeb757e..e2056d8 100644 --- a/src/parser/version.js +++ b/src/parser/version.js @@ -13,12 +13,11 @@ module.exports = function() { if (versions.swagger.includes(global.definition.swagger)) { return 'swagger2' - } else if (versions.openapi3.includes(global.definition.openapi)) { + } else if (versions.openapi3.includes(global.definition.openapi) || versions.openapi31.includes(global.definition.openapi)) { return 'openapi3' - } else if (versions.openapi31.includes(global.definition.openapi)) { - return 'openapi31' + } else { + require('../utils/error.js')('Specification is not supported') } - require('../utils/error.js')('Specification is not supported') }; }() \ No newline at end of file diff --git a/test/parser-authorization.js b/test/parser-authorization.js index da80df7..1c32d83 100644 --- a/test/parser-authorization.js +++ b/test/parser-authorization.js @@ -4,49 +4,49 @@ const assert = require('assert'); describe('parser-authorization', () => { - it('good swagger2', () => { + it('authorization good swagger2', () => { global.definition = require('../seeds/parserAuthorizationInitial.json') const authorization = require('../src/parser/authorization.js')('POST','/apple') assert.deepStrictEqual(authorization, 'user_token') }) - it('endpoint swagger2', () => { + it('authorization endpoint swagger2', () => { global.definition = require('../seeds/parserAuthorizationInitialEndpoint.json') const authorization = require('../src/parser/authorization.js')('POST','/apple') assert.deepStrictEqual(authorization, 'OAuth2') }) - it('general swagger2', () => { + it('authorization general swagger2', () => { global.definition = require('../seeds/parserAuthorizationInitialGeneral.json') const authorization = require('../src/parser/authorization.js')('POST','/apple') assert.deepStrictEqual(authorization, 'BasicAuth') }) - it('general openapi3.0', () => { + it('authorization general openapi3.0', () => { global.definition = require('../seeds/parserAuthorizationInitialOpenApi3.json') const authorization = require('../src/parser/authorization.js')('POST','/pets') assert.deepStrictEqual(authorization, 'ApiKeyAuth') }) - it('endpoint openapi3.0', () => { + it('authorization endpoint openapi3.0', () => { global.definition = require('../seeds/parserAuthorizationInitialOpenApi3.json') const authorization = require('../src/parser/authorization.js')('GET','/pets') assert.deepStrictEqual(authorization, 'OAuth2') }) - it('general openapi3.1', () => { + it('authorization general openapi3.1', () => { global.definition = require('../seeds/parserAuthorizationInitialOpenApi3.1.json') const authorization = require('../src/parser/authorization.js')('POST','/pets') assert.deepStrictEqual(authorization, 'ApiKeyAuth') }) - it('endpoint openapi3.1', () => { + it('authorization endpoint openapi3.1', () => { global.definition = require('../seeds/parserAuthorizationInitialOpenApi3.1.json') const authorization = require('../src/parser/authorization.js')('GET','/pets') diff --git a/test/parser-body.js b/test/parser-body.js index 01e6d92..81646da 100644 --- a/test/parser-body.js +++ b/test/parser-body.js @@ -4,7 +4,7 @@ const assert = require('assert') describe('parser-body', () => { - it('void request swagger2', () => { + it('body void request swagger2', () => { global.definition = require('../seeds/parserInitialGood.json') @@ -12,7 +12,7 @@ describe('parser-body', () => { assert.deepStrictEqual(body, undefined) }) - it('void request openapi3.0', () => { + it('body void request openapi3.0', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.json') @@ -20,7 +20,7 @@ describe('parser-body', () => { assert.deepStrictEqual(body, undefined) }) - it('void request openapi3.0 2', () => { + it('body void request openapi3.0 2', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.json') @@ -28,15 +28,15 @@ describe('parser-body', () => { assert.deepStrictEqual(body, undefined) }) - it('void request openapi3.1', () => { + it('body void request openapi3.1', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') - const body = require('../src/parser/openapi31/body.js')('GET','/pets') + const body = require('../src/parser/openapi3/body.js')('GET','/pets') assert.deepStrictEqual(body, undefined) }) - it('fill request swagger2', () => { + it('body fill request swagger2', () => { global.definition = require('../seeds/parserInitialGood.json') @@ -44,7 +44,7 @@ describe('parser-body', () => { assert.deepStrictEqual(body, {"type":"object","required":["name"],"properties":{"name":{"type":"string"},"tag":{"type":"string"}}}) }) - it('fill request openapi3.0', () => { + it('body fill request openapi3.0', () => { global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') @@ -52,15 +52,15 @@ describe('parser-body', () => { assert.deepStrictEqual(body, {"type":"object","required":["name"],"properties":{"name":{"type":"string"},"tag":{"type":"string"}}}) }) - it('fill request openapi3.1', () => { + it('body fill request openapi3.1', () => { global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') - const body = require('../src/parser/openapi31/body.js')('POST','/pets') + const body = require('../src/parser/openapi3/body.js')('POST','/pets') assert.deepStrictEqual(body, {"type":"object","required":["name"],"properties":{"name":{"type":"string"},"tag":{"type":"string"}}}) }) - it('items, ref and allof response swagger2', () => { + it('body items, ref and allof response swagger2', () => { global.definition = require('../seeds/parserInitialGood.json') @@ -68,7 +68,7 @@ describe('parser-body', () => { assert.deepStrictEqual(body, {"200":{"type":"array","items":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) }) - it('items, ref and allof response openapi3.0', () => { + it('body items, ref and allof response openapi3.0', () => { global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') @@ -76,15 +76,15 @@ describe('parser-body', () => { assert.deepStrictEqual(body, {"200":{"type":"array","items":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) }) - it('items, ref and allof response openapi3.1', () => { + it('body items, ref and allof response openapi3.1', () => { global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') - const body = require('../src/parser/openapi31/body.js')('GET','/pets',true) + const body = require('../src/parser/openapi3/body.js')('GET','/pets',true) assert.deepStrictEqual(body, {"200":{"type":"array","items":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) }) - it('ref and allof response swagger2', () => { + it('body ref and allof response swagger2', () => { global.definition = require('../seeds/parserInitialGood.json') global.circularTail = [] @@ -93,7 +93,7 @@ describe('parser-body', () => { assert.deepStrictEqual(body, {"200":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) }) - it('ref and allof response openapi3.0', () => { + it('body ref and allof response openapi3.0', () => { global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') global.circularTail = [] @@ -102,16 +102,16 @@ describe('parser-body', () => { assert.deepStrictEqual(body, {"200":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) }) - it('ref and allof response openapi3.1', () => { + it('body ref and allof response openapi3.1', () => { global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') global.circularTail = [] - const body = require('../src/parser/openapi31/body.js')('POST','/pets',true) + const body = require('../src/parser/openapi3/body.js')('POST','/pets',true) assert.deepStrictEqual(body, {"200":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) }) - it('allof loop swagger2', () => { + it('body allof loop swagger2', () => { global.definition = require('../seeds/parserBodyAllofLoopInitial.json') @@ -119,7 +119,7 @@ describe('parser-body', () => { assert.deepStrictEqual(body, {"required":["red","orange"],"properties":{"red":{"type":"string","maxLength":50},"orange":{"type":"number","maxLength":9},"water":{"required":["paramAiden"],"properties":{"paramAiden":{"type":"string"},"paramBiden":{"type":"string"},"paramCiden":{"type":"string"}},"type":"object"}},"type":"object"}) }) - it('allof string swagger2', () => { + it('body allof string swagger2', () => { global.definition = require('../seeds/parserBodyAllofString.json') diff --git a/test/parser-consumes.js b/test/parser-consumes.js index 3287804..bb813a2 100644 --- a/test/parser-consumes.js +++ b/test/parser-consumes.js @@ -32,7 +32,7 @@ describe('parser-consumes', () => { global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json'); - const consumes = require('../src/parser/openapi31/consumes.js')('POST','/pets'); + const consumes = require('../src/parser/openapi3/consumes.js')('POST','/pets'); assert.equal(consumes, 'application/json'); }) diff --git a/test/parser-endpoints.js b/test/parser-endpoints.js index 8945b59..5bf03c7 100644 --- a/test/parser-endpoints.js +++ b/test/parser-endpoints.js @@ -17,7 +17,7 @@ before(() => { console.error.restore(); }) - it('bad swagger2', () => { + it('endpoints bad swagger2', () => { global.definition = require('../seeds/parserEndpointsInitialBad.json'); @@ -27,7 +27,7 @@ before(() => { sinon.assert.calledWith(process.exit, 1); }) - it('good swagger2', () => { + it('endpoints good swagger2', () => { global.definition = require('../seeds/parserEndpointsInitialGood.json'); @@ -40,7 +40,7 @@ before(() => { ]) }) - it('good openapi3.0', () => { + it('endpoints good openapi3.0', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.json'); @@ -53,7 +53,7 @@ before(() => { }) - it('good openapi3.1', () => { + it('endpoints good openapi3.1', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json'); diff --git a/test/parser-microcks.js b/test/parser-microcks.js index 04ed2e3..57febeb 100644 --- a/test/parser-microcks.js +++ b/test/parser-microcks.js @@ -34,7 +34,7 @@ describe('parser-microcks', () => { it('specifies openapi3.1', () => { global.definition = require('../seeds/parserMicroksinitialGood3.1.json'); - const microcks = require('../src/parser/openapi31/microcks.js')('GET','/user/{username}'); + const microcks = require('../src/parser/openapi3/microcks.js')('GET','/user/{username}'); assert.equal(microcks, true); }) diff --git a/test/parser-pathParameters.js b/test/parser-pathParameters.js index 1b33214..4ee5cb8 100644 --- a/test/parser-pathParameters.js +++ b/test/parser-pathParameters.js @@ -24,7 +24,7 @@ describe('parser-pathParameters', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') - const status = require('../src/parser/openapi31/pathParameters.js')('GET','/pets/{petId}') + const status = require('../src/parser/openapi3/pathParameters.js')('GET','/pets/{petId}') assert.deepStrictEqual(status, [ { name: 'petId', type: 'string', example: 'asdf' } ]) }) diff --git a/test/parser-queryParams.js b/test/parser-queryParams.js index 231974e..21338ba 100644 --- a/test/parser-queryParams.js +++ b/test/parser-queryParams.js @@ -4,7 +4,7 @@ const assert = require('assert'); describe('parser-queryParams', () => { - it('fill swagger2', () => { + it('queryParams fill swagger2', () => { global.definition = require('../seeds/parserQueryParamsGood.json') @@ -21,7 +21,7 @@ describe('parser-queryParams', () => { } ]) }) - it('void swagger2', () => { + it('queryParams void swagger2', () => { global.definition = require('../seeds/parserQueryParamsGood.json') @@ -29,7 +29,7 @@ describe('parser-queryParams', () => { assert.deepStrictEqual(queryParams, []) }) - it('fill openapi3.0', () => { + it('queryParams fill openapi3.0', () => { global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') @@ -46,7 +46,7 @@ describe('parser-queryParams', () => { } ]) }) - it('void openapi3.0', () => { + it('queryParams void openapi3.0', () => { global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') @@ -54,11 +54,11 @@ describe('parser-queryParams', () => { assert.deepStrictEqual(queryParams, []) }) - it('fill openapi3.1', () => { + it('queryParams fill openapi3.1', () => { global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') - const queryParams = require('../src/parser/openapi31/queryParams.js')('GET','/pets') + const queryParams = require('../src/parser/openapi3/queryParams.js')('GET','/pets') assert.deepStrictEqual(queryParams, [{ "name": "tags", "required": false, @@ -71,11 +71,11 @@ describe('parser-queryParams', () => { } ]) }) - it('void openapi3.1', () => { + it('queryParams void openapi3.1', () => { global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') - const queryParams = require('../src/parser/openapi31/queryParams.js')('POST','/pets') + const queryParams = require('../src/parser/openapi3/queryParams.js')('POST','/pets') assert.deepStrictEqual(queryParams, []) }) }) \ No newline at end of file diff --git a/test/parser-schemaHostBasePath.js b/test/parser-schemaHostBasePath.js index 167914f..52876ba 100644 --- a/test/parser-schemaHostBasePath.js +++ b/test/parser-schemaHostBasePath.js @@ -24,7 +24,7 @@ describe('parser-schemaHostBasePath', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json'); - const schemaHostBasePath = require('../src/parser/openapi31/schemaHostBasePath.js')(); - assert.deepStrictEqual(schemaHostBasePath, { host: 'http://petstore.swagger.io', basePath: '/v1' }); + const schemaHostBasePath = require('../src/parser/openapi3/schemaHostBasePath.js')(); + assert.deepStrictEqual(schemaHostBasePath, { host: 'https://petstore.swagger.io', basePath: '/v1' }); }) }); \ No newline at end of file diff --git a/test/parser-version.js b/test/parser-version.js index a6e3990..2553f64 100644 --- a/test/parser-version.js +++ b/test/parser-version.js @@ -41,7 +41,7 @@ describe('parser-version', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') const version = require('../src/parser/version.js')() - assert.equal(version, 'openapi31') + assert.equal(version, 'openapi3') }); it('openapi version 3.1.1' , () => { @@ -49,7 +49,7 @@ describe('parser-version', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.1.1.json') const version = require('../src/parser/version.js')() - assert.equal(version, 'openapi31') + assert.equal(version, 'openapi3') }) it('openapi version 3.1.2' , () => { @@ -57,6 +57,6 @@ describe('parser-version', () => { global.definition = require('../seeds/parserInitialGoodOpenApi3.1.2.json') const version = require('../src/parser/version.js')() - assert.equal(version, 'openapi31') + assert.equal(version, 'openapi3') }) }); \ No newline at end of file From f1978f81efa13095dc16ba24e4216565c2a72ffa Mon Sep 17 00:00:00 2001 From: Melsy Huamani Date: Mon, 2 Mar 2026 10:14:15 -0500 Subject: [PATCH 6/8] fix: parser and tests sonarqube new issues --- src/generator/endpoints.js | 6 +- src/generator/examples.js | 8 +- src/parser/endpoints.js | 6 +- src/parser/openapi3/body.js | 50 ++-------- src/parser/openapi3/consumes.js | 6 +- src/parser/openapi3/headers.js | 6 +- src/parser/openapi3/microcks.js | 6 +- src/parser/openapi3/pathParameters.js | 6 +- src/parser/openapi3/queryParams.js | 16 ++-- src/parser/openapi3/schemaHostBasePath.js | 4 +- src/parser/status.js | 6 +- src/parser/summary.js | 6 +- src/parser/swagger2/body.js | 52 ++-------- src/parser/swagger2/queryParams.js | 12 +-- src/parser/version.js | 4 +- src/swagger2json/index.js | 18 ++-- src/utils/circularRef.js | 32 +++++++ test/parser-authorization.js | 69 ++++--------- test/parser-body.js | 36 +++---- test/parser-consumes.js | 8 +- test/parser-endpoints.js | 112 +++++++++++----------- test/parser-microcks.js | 8 +- test/parser-pathParameters.js | 6 +- test/parser-queryParams.js | 91 ++++-------------- test/parser-schemaHostBasePath.js | 6 +- test/parser-status.js | 6 +- test/parser-summary.js | 6 +- test/parser-version.js | 14 +-- 28 files changed, 245 insertions(+), 361 deletions(-) create mode 100644 src/utils/circularRef.js diff --git a/src/generator/endpoints.js b/src/generator/endpoints.js index 69c3e20..05cd6c8 100644 --- a/src/generator/endpoints.js +++ b/src/generator/endpoints.js @@ -14,7 +14,7 @@ module.exports = function() { _.forEach(endpoint.pathParameters, function(pathParameter) { pathParameterSaved = pathParameter; path = _.replace(path, '{'+pathParameter.name+'}', '{{'+pathParameter.name+'}}') - global.environmentVariables[endpoint.verb+endpoint.path.slice(1)+pathParameter.name] = require('../utils/exampleForField.js')(pathParameter,false) + globalThis.environmentVariables[endpoint.verb+endpoint.path.slice(1)+pathParameter.name] = require('../utils/exampleForField.js')(pathParameter,false) }); _.forEach(endpoint.status,function(response) { let item = { @@ -66,7 +66,7 @@ module.exports = function() { } // Duplicar los endpoints para cada queryParameter dependiendo si el minimal endpoint está en true o false - if(!global.configurationFile?.minimal_endpoints || global.configurationFile?.minimal_endpoints === false){ + if(!globalThis.configurationFile?.minimal_endpoints || globalThis.configurationFile?.minimal_endpoints === false){ if (item.aux.status >= 200 && item.aux.status < 400 && item.aux.queryParams.length > 0) { addQueryParamEndpoint(item, items); } @@ -114,7 +114,7 @@ module.exports = function() { } function countRequest(endpoint){ - if (!global.configurationFile?.generate_oneOf_anyOf) { + if (!globalThis.configurationFile?.generate_oneOf_anyOf) { return 1; } diff --git a/src/generator/examples.js b/src/generator/examples.js index b21ed34..6323b81 100644 --- a/src/generator/examples.js +++ b/src/generator/examples.js @@ -4,8 +4,8 @@ const _ = require("lodash"); module.exports = (function () { return function get(path, method, status) { - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); + const hasPaths = _.isObject(globalThis.definition.paths); + const hasWebhooks = _.isObject(globalThis.definition.webhooks); if (!hasPaths) { if (hasWebhooks) return null; @@ -16,12 +16,12 @@ module.exports = (function () { path = '/' + path; } - if (!global.definition.paths[path]) { + if (!globalThis.definition.paths[path]) { return null; } const methodLower = _.toLower(method); - const endpoint = global.definition.paths[path][methodLower]; + const endpoint = globalThis.definition.paths[path][methodLower]; if (!endpoint) { return null; diff --git a/src/parser/endpoints.js b/src/parser/endpoints.js index f58bc1c..2563283 100644 --- a/src/parser/endpoints.js +++ b/src/parser/endpoints.js @@ -7,8 +7,8 @@ const _ = require('lodash'); module.exports = function () { return function get() { - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); + const hasPaths = _.isObject(globalThis.definition.paths); + const hasWebhooks = _.isObject(globalThis.definition.webhooks); if (!hasPaths) { if (hasWebhooks) return []; @@ -16,7 +16,7 @@ module.exports = function () { } const items = []; - _.forEach(global.definition.paths, function (pathInfo, path) { + _.forEach(globalThis.definition.paths, function (pathInfo, path) { _.forEach(pathInfo, function (verbInfo, verb) { items.push({ 'verb': _.toUpper(verb), diff --git a/src/parser/openapi3/body.js b/src/parser/openapi3/body.js index d189059..d418935 100644 --- a/src/parser/openapi3/body.js +++ b/src/parser/openapi3/body.js @@ -3,6 +3,7 @@ 'use strict' const _ = require('lodash') +const checkCircularReferences = require('../../utils/circularRef.js'); module.exports = function () { @@ -12,14 +13,14 @@ module.exports = function () { return function get(verb, path, bodyResponse) { seenSchemas = new WeakSet(); - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); + const hasPaths = _.isObject(globalThis.definition.paths); + const hasWebhooks = _.isObject(globalThis.definition.webhooks); if (!hasPaths) { if (hasWebhooks) return bodyResponse ? {} : undefined; require('../../utils/error.js')('paths is required'); } - const endpoint = global.definition.paths[path][_.toLower(verb)] + const endpoint = globalThis.definition.paths[path][_.toLower(verb)] if (!endpoint) return undefined; if (!bodyResponse) { @@ -29,7 +30,7 @@ module.exports = function () { if (body['$ref']) { let componentType = body['$ref'].split('/')[2] const ref = _.replace(body['$ref'], '#/components/' + componentType + '/', '') - body = global.definition.components[componentType][ref] + body = globalThis.definition.components[componentType][ref] } if (!body.content['application/json']) { const contentsArray = Object.keys(body.content); @@ -70,7 +71,7 @@ module.exports = function () { const firstContentType = contentsArray[0]; const mediaType = body.content[firstContentType]; - if (mediaType && mediaType.schema) { + if (mediaType?.schema) { const withoutRefs = replaceRefs(mediaType.schema, 1); return replaceAllOfs(withoutRefs); } @@ -115,7 +116,7 @@ module.exports = function () { } } - let entity = global.definition.components[componentType][ref] + let entity = globalThis.definition.components[componentType][ref] if (!entity) { require('../../utils/error.js')('ref ' + ref + ' is not defined') } @@ -240,41 +241,4 @@ module.exports = function () { return result } - function checkCircularReferences(reference, depthLevel, patternNumber) { - if (!global.circularTail) { - global.circularTail = [] - } - if (!global.circularTail[patternNumber]) { - global.circularTail[patternNumber] = [reference] - return false - } - if (global.circularTail[patternNumber].length < (depthLevel * patternNumber)) { - global.circularTail[patternNumber].push(reference) - return false - } - - const groups = _.chunk(global.circularTail[patternNumber], patternNumber) - global.circularTail[patternNumber].shift() - global.circularTail[patternNumber].push(reference) - - let areEquals = true - let lastArray = groups[0] - comparation: - for (let i = 1; i < groups.length; i++) { - for (let k in groups[i]) { - if (groups[i][k] !== groups[i - 1][k]) { - areEquals = false - break comparation - } - } - } - - if (areEquals) { - global.circularTail = [] - } - - return areEquals - - } - }() \ No newline at end of file diff --git a/src/parser/openapi3/consumes.js b/src/parser/openapi3/consumes.js index 7345c13..2f5aa5b 100644 --- a/src/parser/openapi3/consumes.js +++ b/src/parser/openapi3/consumes.js @@ -7,15 +7,15 @@ const _ = require('lodash'); module.exports = function () { return function get(verb, path) { - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); + const hasPaths = _.isObject(globalThis.definition.paths); + const hasWebhooks = _.isObject(globalThis.definition.webhooks); if (!hasPaths) { if (hasWebhooks) return 'application/json'; require('../../utils/error.js')('paths is required'); } - const request = global.definition.paths[path][_.toLower(verb)] + const request = globalThis.definition.paths[path][_.toLower(verb)] if (request.requestBody && request.requestBody.content) { return _.keys(request.requestBody.content)[0] } diff --git a/src/parser/openapi3/headers.js b/src/parser/openapi3/headers.js index 29c1d7f..50a321c 100644 --- a/src/parser/openapi3/headers.js +++ b/src/parser/openapi3/headers.js @@ -7,15 +7,15 @@ const _ = require('lodash'); module.exports = function () { return function get(verb, path) { - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); + const hasPaths = _.isObject(globalThis.definition.paths); + const hasWebhooks = _.isObject(globalThis.definition.webhooks); if (!hasPaths) { if (hasWebhooks) return []; require('../../utils/error.js')('paths is required'); } - let parameters = global.definition.paths[path][_.toLower(verb)]['parameters']; + let parameters = globalThis.definition.paths[path][_.toLower(verb)]['parameters']; let headers = _.filter(parameters, ['in', 'header']) const result = [] _.forEach(headers, function (header) { diff --git a/src/parser/openapi3/microcks.js b/src/parser/openapi3/microcks.js index f4644c5..7660d81 100644 --- a/src/parser/openapi3/microcks.js +++ b/src/parser/openapi3/microcks.js @@ -1,15 +1,15 @@ const _ = require('lodash'); module.exports = (function (verb, path) { - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); + const hasPaths = _.isObject(globalThis.definition.paths); + const hasWebhooks = _.isObject(globalThis.definition.webhooks); if (!hasPaths) { if (hasWebhooks) return false; require('../../utils/error.js')('paths is required'); } - const endpoint = global.definition.paths[path][_.toLower(verb)] + const endpoint = globalThis.definition.paths[path][_.toLower(verb)] return !!endpoint["x-microcks-operation"] }) \ No newline at end of file diff --git a/src/parser/openapi3/pathParameters.js b/src/parser/openapi3/pathParameters.js index f1f5fef..39bebaa 100644 --- a/src/parser/openapi3/pathParameters.js +++ b/src/parser/openapi3/pathParameters.js @@ -7,15 +7,15 @@ const _ = require('lodash') module.exports = function () { return function get(verb, path) { - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); + const hasPaths = _.isObject(globalThis.definition.paths); + const hasWebhooks = _.isObject(globalThis.definition.webhooks); if (!hasPaths) { if (hasWebhooks) return []; require('../../utils/error.js')('paths is required'); } - const parameters = global.definition.paths[path][_.toLower(verb)]['parameters'] + const parameters = globalThis.definition.paths[path][_.toLower(verb)]['parameters'] const parametersPath = _.filter(parameters, ['in', 'path']) const result = [] _.forEach(parametersPath, function (parameterPath) { diff --git a/src/parser/openapi3/queryParams.js b/src/parser/openapi3/queryParams.js index 0e0145f..6640fcf 100644 --- a/src/parser/openapi3/queryParams.js +++ b/src/parser/openapi3/queryParams.js @@ -7,10 +7,10 @@ const _ = require('lodash'); module.exports = function() { return function get(verb,path){ - if (!_.isObject(global.definition.paths)) { + if (!_.isObject(globalThis.definition.paths)) { } - let parameters = global.definition.paths[path][_.toLower(verb)]['parameters']; + let parameters = globalThis.definition.paths[path][_.toLower(verb)]['parameters']; // parameters = replaceRefs(parameters); let queryParams = _.filter(parameters, ['in', 'query']) const result = [] @@ -41,11 +41,11 @@ module.exports = function() { if (i === '$ref'){ const ref = _.replace(schema[i], '#/components/parameters/', ''); const schemaRef = _.replace(schema[i], '#/components/schemas/', ''); - let entity = global.definition.components.parameters[ref] || global.definition.components.schemas[schemaRef]; + let entity = globalThis.definition.components.parameters[ref] || globalThis.definition.components.schemas[schemaRef]; if (!entity){ require('../../utils/error.js')('ref '+ref+' is not defined') } - entity = replaceRefs(entity,global.definition) + entity = replaceRefs(entity,globalThis.definition) result = _.merge(result, entity) } else if ( _.isArray(schema[i]) && i !== 'required'){ const arrayResult = [] @@ -53,11 +53,11 @@ module.exports = function() { continue; } for (let k in schema[i]) { - arrayResult.push(replaceRefs(schema[i][k],global.definition)) + arrayResult.push(replaceRefs(schema[i][k],globalThis.definition)) } result[i] = arrayResult } else if ( _.isObject(schema[i]) && i !== 'required'){ - result[i] = replaceRefs(schema[i],global.definition) + result[i] = replaceRefs(schema[i],globalThis.definition) } else { result[i] = schema[i]; } @@ -66,7 +66,7 @@ module.exports = function() { } function getExamples(queryParam) { - if (!queryParam || !queryParam.schema) return undefined; + if (!queryParam?.schema) return undefined; if (queryParam.schema.type === 'array') { return queryParam.example; @@ -79,7 +79,7 @@ module.exports = function() { if (queryParam.hasOwnProperty('examples')) { const firstKey = Object.keys(queryParam.examples)[0]; const value = queryParam.examples[firstKey]; - if (value && value.hasOwnProperty('value')) { + if (value?.hasOwnProperty('value')) { return value.value; } return value; diff --git a/src/parser/openapi3/schemaHostBasePath.js b/src/parser/openapi3/schemaHostBasePath.js index 14c693b..3d2fc8e 100644 --- a/src/parser/openapi3/schemaHostBasePath.js +++ b/src/parser/openapi3/schemaHostBasePath.js @@ -7,10 +7,10 @@ const _ = require('lodash'); module.exports = function() { return function get(){ - if (!global.definition.servers || !_.isArray(global.definition.servers) || !global.definition.servers[0] || !global.definition.servers[0].url || !_.isString(global.definition.servers[0].url)) { + if (!globalThis.definition.servers || !_.isArray(globalThis.definition.servers) || !globalThis.definition.servers[0] || !globalThis.definition.servers[0].url || !_.isString(globalThis.definition.servers[0].url)) { require('../../utils/error.js')('servers is required') } - const all = global.definition.servers[0].url + const all = globalThis.definition.servers[0].url const allArray = all.split( '/' ) const protocol = allArray[0] if (protocol !== 'http:' && protocol !== 'https:' && protocol !== '{scheme}:') { diff --git a/src/parser/status.js b/src/parser/status.js index 093897e..c2e12e2 100644 --- a/src/parser/status.js +++ b/src/parser/status.js @@ -7,15 +7,15 @@ const _ = require('lodash'); module.exports = function () { return function get(verb, path) { - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); + const hasPaths = _.isObject(globalThis.definition.paths); + const hasWebhooks = _.isObject(globalThis.definition.webhooks); if (!hasPaths) { if (hasWebhooks) return []; require('../../utils/error.js')('paths is required'); } - const responses = global.definition.paths[path][_.toLower(verb)]['responses'] + const responses = globalThis.definition.paths[path][_.toLower(verb)]['responses'] const keys = _.keys(responses) for (const index in keys) { keys[index] = _.toInteger(keys[index]) diff --git a/src/parser/summary.js b/src/parser/summary.js index 49f9e81..4c5a669 100644 --- a/src/parser/summary.js +++ b/src/parser/summary.js @@ -7,15 +7,15 @@ const _ = require('lodash') module.exports = function () { return function get(verb, path) { - const hasPaths = _.isObject(global.definition.paths); - const hasWebhooks = _.isObject(global.definition.webhooks); + const hasPaths = _.isObject(globalThis.definition.paths); + const hasWebhooks = _.isObject(globalThis.definition.webhooks); if (!hasPaths) { if (hasWebhooks) return false; require('../../utils/error.js')('paths is required'); } - const endpoint = global.definition.paths[path][_.toLower(verb)] + const endpoint = globalThis.definition.paths[path][_.toLower(verb)] if (_.has(endpoint, 'summary')) { return endpoint.summary } diff --git a/src/parser/swagger2/body.js b/src/parser/swagger2/body.js index 856d3c7..0466871 100644 --- a/src/parser/swagger2/body.js +++ b/src/parser/swagger2/body.js @@ -3,6 +3,7 @@ 'use strict' const _ = require('lodash'); +const checkCircularReferences = require('../../utils/circularRef.js'); module.exports = function() { @@ -10,11 +11,11 @@ module.exports = function() { return function get(verb, path, bodyResponse) { seenSchemas = new WeakSet(); - if (!_.isObject(global.definition.paths)) { + if (!_.isObject(globalThis.definition.paths)) { require('../../utils/error.js')('paths is required'); } - const endpoint = global.definition.paths[path][_.toLower(verb)]; + const endpoint = globalThis.definition.paths[path][_.toLower(verb)]; if (!bodyResponse){ let bodyParameter = replaceRefs(endpoint['parameters']); const body = _.find(bodyParameter, ['in', 'body']); @@ -62,14 +63,14 @@ module.exports = function() { description: 'Circular REF solved swagger2postman' } } - let entity = global.definition.definitions[ref]; + let entity = globalThis.definition.definitions[ref]; if (!entity){ - entity = global.definition.parameters[ref]; + entity = globalThis.definition.parameters[ref]; if (!entity) { require('../../utils/error.js')('ref ' + ref + ' is not defined'); } } - entity = replaceRefs(entity, global.definition); + entity = replaceRefs(entity, globalThis.definition); result = _.merge(result, entity); } else if ( _.isArray(schema[i]) && i !== 'required'){ const arrayResult = []; @@ -77,11 +78,11 @@ module.exports = function() { continue; } for (let k in schema[i]) { - arrayResult.push(replaceRefs(schema[i][k],global.definition)); + arrayResult.push(replaceRefs(schema[i][k],globalThis.definition)); } result[i] = arrayResult; } else if ( _.isObject(schema[i]) && i !== 'required'){ - result[i] = replaceRefs(schema[i],global.definition); + result[i] = replaceRefs(schema[i],globalThis.definition); } else { result[i] = schema[i]; } @@ -146,41 +147,4 @@ module.exports = function() { return result; } - function checkCircularReferences(reference, depthLevel, patternNumber){ - if (!global.circularTail){ - global.circularTail = [] - } - if (! global.circularTail[patternNumber] ){ - global.circularTail[patternNumber] = [reference] - return false - } - if (global.circularTail[patternNumber].length < (depthLevel * patternNumber) ){ - global.circularTail[patternNumber].push(reference) - return false - } - - const groups = _.chunk(global.circularTail[patternNumber], patternNumber) - global.circularTail[patternNumber].shift() - global.circularTail[patternNumber].push(reference) - - let areEquals = true - let lastArray = groups[0] - comparation: - for (let i = 1; i < groups.length; i++) { - for (let k in groups[i]){ - if (groups[i][k] !== groups[i - 1][k]){ - areEquals = false - break comparation - } - } - } - - if (areEquals){ - global.circularTail = [] - } - - return areEquals - - } - }() \ No newline at end of file diff --git a/src/parser/swagger2/queryParams.js b/src/parser/swagger2/queryParams.js index 54c565b..d319434 100644 --- a/src/parser/swagger2/queryParams.js +++ b/src/parser/swagger2/queryParams.js @@ -7,11 +7,11 @@ const _ = require('lodash'); module.exports = function() { return function get(verb,path){ - if (!_.isObject(global.definition.paths)) { + if (!_.isObject(globalThis.definition.paths)) { require('../../utils/error.js')('paths is required') } - let parameters = global.definition.paths[path][_.toLower(verb)]['parameters']; + let parameters = globalThis.definition.paths[path][_.toLower(verb)]['parameters']; // parameters = replaceRefs(parameters); const queryParams = _.filter(parameters, ['in', 'query']) const result = [] @@ -38,11 +38,11 @@ module.exports = function() { for (let i in schema) { if (i === '$ref'){ const ref = _.replace(schema[i], '#/parameters/', ''); - let entity = global.definition.parameters[ref]; + let entity = globalThis.definition.parameters[ref]; if (!entity){ continue; } - entity = replaceRefs(entity, global.definition); + entity = replaceRefs(entity, globalThis.definition); result = _.merge(result, entity); } else if (_.isArray(schema[i]) && i !== 'required'){ const arrayResult = []; @@ -50,11 +50,11 @@ module.exports = function() { continue; } for (let k in schema[i]) { - arrayResult.push(replaceRefs(schema[i][k],global.definition)); + arrayResult.push(replaceRefs(schema[i][k],globalThis.definition)); } result[i] = arrayResult; } else if (_.isObject(schema[i]) && i !== 'required'){ - result[i] = replaceRefs(schema[i],global.definition); + result[i] = replaceRefs(schema[i],globalThis.definition); } else { result[i] = schema[i]; } diff --git a/src/parser/version.js b/src/parser/version.js index e2056d8..534bd7f 100644 --- a/src/parser/version.js +++ b/src/parser/version.js @@ -11,9 +11,9 @@ module.exports = function() { openapi31 : ['3.1', '3.1.0', '3.1.1', '3.1.2'] } - if (versions.swagger.includes(global.definition.swagger)) { + if (versions.swagger.includes(globalThis.definition.swagger)) { return 'swagger2' - } else if (versions.openapi3.includes(global.definition.openapi) || versions.openapi31.includes(global.definition.openapi)) { + } else if (versions.openapi3.includes(globalThis.definition.openapi) || versions.openapi31.includes(globalThis.definition.openapi)) { return 'openapi3' } else { require('../utils/error.js')('Specification is not supported') diff --git a/src/swagger2json/index.js b/src/swagger2json/index.js index fa5d62b..646dcde 100644 --- a/src/swagger2json/index.js +++ b/src/swagger2json/index.js @@ -16,7 +16,7 @@ module.exports = function () { return t }) - const nonNullTypes = swagger.type.filter(t => t !== 'null'); + const nonNullTypes = swagger.type.find(t => t !== 'null'); swagger.type = nonNullTypes[0] || 'string'; } @@ -39,9 +39,9 @@ module.exports = function () { } let wrongParam = false; - if (parent && global.wrongParamsCatch && _.indexOf(global.wrongParams, parent) === -1 && parent !== 'with') { - global.wrongParams.push(parent); - global.wrongParamsCatch = false; + if (parent && globalThis.wrongParamsCatch && _.indexOf(globalThis.wrongParams, parent) === -1 && parent !== 'with') { + globalThis.wrongParams.push(parent); + globalThis.wrongParamsCatch = false; wrongParam = true; } @@ -49,7 +49,7 @@ module.exports = function () { case 'object': if (wrongParam) { - global.environmentVariables[global.currentId + name + '_wrong'] = require('../utils/exampleForField.js')(swagger, true) + globalThis.environmentVariables[globalThis.currentId + name + '_wrong'] = require('../utils/exampleForField.js')(swagger, true) return '{{' + name + '_wrong}}' } @@ -57,7 +57,7 @@ module.exports = function () { case 'array': if (wrongParam) { - global.environmentVariables[global.currentId + name + '_wrong'] = require('../utils/exampleForField.js')(swagger, true) + globalThis.environmentVariables[globalThis.currentId + name + '_wrong'] = require('../utils/exampleForField.js')(swagger, true) return '{{' + name + '_wrong}}' } @@ -68,10 +68,10 @@ module.exports = function () { case 'boolean': if (wrongParam) { - global.environmentVariables[global.currentId + name + '_wrong'] = require('../utils/exampleForField.js')(swagger, true) + globalThis.environmentVariables[globalThis.currentId + name + '_wrong'] = require('../utils/exampleForField.js')(swagger, true) return '{{' + name + '_wrong}}' } - global.environmentVariables[global.currentId + name] = require('../utils/exampleForField.js')(swagger, false) + globalThis.environmentVariables[globalThis.currentId + name] = require('../utils/exampleForField.js')(swagger, false) return '{{' + name + '}}' case 'oneOf': let schemaOne = swagger.oneOf[index]; @@ -91,7 +91,7 @@ module.exports = function () { case 'array': return require('./array.js')(schema, name, parent); default: - global.environmentVariables[global.currentId + name] = require('../utils/exampleForField.js')(schema, false); + globalThis.environmentVariables[globalThis.currentId + name] = require('../utils/exampleForField.js')(schema, false); return '{{' + name + '}}'; } } diff --git a/src/utils/circularRef.js b/src/utils/circularRef.js new file mode 100644 index 0000000..031c820 --- /dev/null +++ b/src/utils/circularRef.js @@ -0,0 +1,32 @@ +/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ + +'use strict' + + +const _ = require('lodash'); + +module.exports = function checkCircularReferences(reference, depthLevel, patternNumber) { + const tail = globalThis.circularTail = globalThis.circularTail || []; + + if (!tail[patternNumber]) { + tail[patternNumber] = [reference]; + return false; + } + + const currentPattern = tail[patternNumber]; + + if (currentPattern.length < (depthLevel * patternNumber)) { + currentPattern.push(reference); + return false; + } + + currentPattern.shift(); + currentPattern.push(reference); + + const groups = _.chunk(currentPattern, patternNumber); + const areEquals = groups.length > 1 && groups.every(group => _.isEqual(group, groups[0])); + + if (areEquals) globalThis.circularTail = []; + + return areEquals; +}; \ No newline at end of file diff --git a/test/parser-authorization.js b/test/parser-authorization.js index 1c32d83..5152b54 100644 --- a/test/parser-authorization.js +++ b/test/parser-authorization.js @@ -1,55 +1,26 @@ /** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ const assert = require('assert'); +const getAuthorization = require('../src/parser/authorization.js'); describe('parser-authorization', () => { - - it('authorization good swagger2', () => { - global.definition = require('../seeds/parserAuthorizationInitial.json') - const authorization = require('../src/parser/authorization.js')('POST','/apple') - assert.deepStrictEqual(authorization, 'user_token') - }) - - it('authorization endpoint swagger2', () => { - - global.definition = require('../seeds/parserAuthorizationInitialEndpoint.json') - const authorization = require('../src/parser/authorization.js')('POST','/apple') - assert.deepStrictEqual(authorization, 'OAuth2') - }) - - it('authorization general swagger2', () => { - - global.definition = require('../seeds/parserAuthorizationInitialGeneral.json') - const authorization = require('../src/parser/authorization.js')('POST','/apple') - assert.deepStrictEqual(authorization, 'BasicAuth') - }) - - it('authorization general openapi3.0', () => { - - global.definition = require('../seeds/parserAuthorizationInitialOpenApi3.json') - const authorization = require('../src/parser/authorization.js')('POST','/pets') - assert.deepStrictEqual(authorization, 'ApiKeyAuth') - }) - - it('authorization endpoint openapi3.0', () => { - - global.definition = require('../seeds/parserAuthorizationInitialOpenApi3.json') - const authorization = require('../src/parser/authorization.js')('GET','/pets') - assert.deepStrictEqual(authorization, 'OAuth2') - }) - - it('authorization general openapi3.1', () => { - - global.definition = require('../seeds/parserAuthorizationInitialOpenApi3.1.json') - const authorization = require('../src/parser/authorization.js')('POST','/pets') - assert.deepStrictEqual(authorization, 'ApiKeyAuth') - }) - - it('authorization endpoint openapi3.1', () => { - - global.definition = require('../seeds/parserAuthorizationInitialOpenApi3.1.json') - const authorization = require('../src/parser/authorization.js')('GET','/pets') - assert.deepStrictEqual(authorization, 'OAuth2') - }) -}) \ No newline at end of file + const testCases = [ + { name: 'authorization good swagger2', seed: 'parserAuthorizationInitial.json', method: 'POST', path: '/apple', expected: 'user_token' }, + { name: 'authorization endpoint swagger2', seed: 'parserAuthorizationInitialEndpoint.json', method: 'POST', path: '/apple', expected: 'OAuth2' }, + { name: 'authorization general swagger2', seed: 'parserAuthorizationInitialGeneral.json', method: 'POST', path: '/apple', expected: 'BasicAuth' }, + { name: 'authorization general openapi3.0', seed: 'parserAuthorizationInitialOpenApi3.json', method: 'POST', path: '/pets', expected: 'ApiKeyAuth' }, + { name: 'authorization endpoint openapi3.0', seed: 'parserAuthorizationInitialOpenApi3.json', method: 'GET', path: '/pets', expected: 'OAuth2' }, + { name: 'authorization general openapi3.1', seed: 'parserAuthorizationInitialOpenApi3.1.json', method: 'POST', path: '/pets', expected: 'ApiKeyAuth' }, + { name: 'authorization endpoint openapi3.1', seed: 'parserAuthorizationInitialOpenApi3.1.json', method: 'GET', path: '/pets', expected: 'OAuth2' } + ]; + + testCases.forEach(({ name, seed, method, path, expected }) => { + it(name, () => { + globalThis.definition = require(`../seeds/${seed}`); + const authorization = getAuthorization(method, path); + assert.deepStrictEqual(authorization, expected); + }); + }); + +}); \ No newline at end of file diff --git a/test/parser-body.js b/test/parser-body.js index 81646da..4aa1380 100644 --- a/test/parser-body.js +++ b/test/parser-body.js @@ -6,7 +6,7 @@ describe('parser-body', () => { it('body void request swagger2', () => { - global.definition = require('../seeds/parserInitialGood.json') + globalThis.definition = require('../seeds/parserInitialGood.json') const body = require('../src/parser/swagger2/body.js')('GET','/pets') assert.deepStrictEqual(body, undefined) @@ -14,7 +14,7 @@ describe('parser-body', () => { it('body void request openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.json') const body = require('../src/parser/openapi3/body.js')('GET','/pets') assert.deepStrictEqual(body, undefined) @@ -22,7 +22,7 @@ describe('parser-body', () => { it('body void request openapi3.0 2', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.json') const body = require('../src/parser/openapi3/body.js')('POST','/pets') assert.deepStrictEqual(body, undefined) @@ -30,7 +30,7 @@ describe('parser-body', () => { it('body void request openapi3.1', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') const body = require('../src/parser/openapi3/body.js')('GET','/pets') assert.deepStrictEqual(body, undefined) @@ -38,7 +38,7 @@ describe('parser-body', () => { it('body fill request swagger2', () => { - global.definition = require('../seeds/parserInitialGood.json') + globalThis.definition = require('../seeds/parserInitialGood.json') const body = require('../src/parser/swagger2/body.js')('POST','/pets') assert.deepStrictEqual(body, {"type":"object","required":["name"],"properties":{"name":{"type":"string"},"tag":{"type":"string"}}}) @@ -46,7 +46,7 @@ describe('parser-body', () => { it('body fill request openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') const body = require('../src/parser/openapi3/body.js')('POST','/pets') assert.deepStrictEqual(body, {"type":"object","required":["name"],"properties":{"name":{"type":"string"},"tag":{"type":"string"}}}) @@ -54,7 +54,7 @@ describe('parser-body', () => { it('body fill request openapi3.1', () => { - global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') const body = require('../src/parser/openapi3/body.js')('POST','/pets') assert.deepStrictEqual(body, {"type":"object","required":["name"],"properties":{"name":{"type":"string"},"tag":{"type":"string"}}}) @@ -62,7 +62,7 @@ describe('parser-body', () => { it('body items, ref and allof response swagger2', () => { - global.definition = require('../seeds/parserInitialGood.json') + globalThis.definition = require('../seeds/parserInitialGood.json') const body = require('../src/parser/swagger2/body.js')('GET','/pets',true) assert.deepStrictEqual(body, {"200":{"type":"array","items":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) @@ -70,7 +70,7 @@ describe('parser-body', () => { it('body items, ref and allof response openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') const body = require('../src/parser/openapi3/body.js')('GET','/pets',true) assert.deepStrictEqual(body, {"200":{"type":"array","items":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) @@ -78,7 +78,7 @@ describe('parser-body', () => { it('body items, ref and allof response openapi3.1', () => { - global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') const body = require('../src/parser/openapi3/body.js')('GET','/pets',true) assert.deepStrictEqual(body, {"200":{"type":"array","items":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) @@ -86,8 +86,8 @@ describe('parser-body', () => { it('body ref and allof response swagger2', () => { - global.definition = require('../seeds/parserInitialGood.json') - global.circularTail = [] + globalThis.definition = require('../seeds/parserInitialGood.json') + globalThis.circularTail = [] const body = require('../src/parser/swagger2/body.js')('POST','/pets',true) assert.deepStrictEqual(body, {"200":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) @@ -95,8 +95,8 @@ describe('parser-body', () => { it('body ref and allof response openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') - global.circularTail = [] + globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') + globalThis.circularTail = [] const body = require('../src/parser/openapi3/body.js')('POST','/pets',true) assert.deepStrictEqual(body, {"200":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) @@ -104,8 +104,8 @@ describe('parser-body', () => { it('body ref and allof response openapi3.1', () => { - global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') - global.circularTail = [] + globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') + globalThis.circularTail = [] const body = require('../src/parser/openapi3/body.js')('POST','/pets',true) assert.deepStrictEqual(body, {"200":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) @@ -113,7 +113,7 @@ describe('parser-body', () => { it('body allof loop swagger2', () => { - global.definition = require('../seeds/parserBodyAllofLoopInitial.json') + globalThis.definition = require('../seeds/parserBodyAllofLoopInitial.json') const body = require('../src/parser/swagger2/body.js')('POST','/apple') assert.deepStrictEqual(body, {"required":["red","orange"],"properties":{"red":{"type":"string","maxLength":50},"orange":{"type":"number","maxLength":9},"water":{"required":["paramAiden"],"properties":{"paramAiden":{"type":"string"},"paramBiden":{"type":"string"},"paramCiden":{"type":"string"}},"type":"object"}},"type":"object"}) @@ -121,7 +121,7 @@ describe('parser-body', () => { it('body allof string swagger2', () => { - global.definition = require('../seeds/parserBodyAllofString.json') + globalThis.definition = require('../seeds/parserBodyAllofString.json') const body = require('../src/parser/swagger2/body.js')('POST','/apple') assert.deepStrictEqual(body, {"type":"object","properties":{"red":{"type":"string","maxLength":50}}}) diff --git a/test/parser-consumes.js b/test/parser-consumes.js index bb813a2..769d1ea 100644 --- a/test/parser-consumes.js +++ b/test/parser-consumes.js @@ -6,7 +6,7 @@ describe('parser-consumes', () => { it('general swagger2', () => { - global.definition = require('../seeds/parserConsumesInitial.json') + globalThis.definition = require('../seeds/parserConsumesInitial.json') const consumes = require('../src/parser/swagger2/consumes.js')('POST','/pets/{id}') assert.equal(consumes, 'application/json') @@ -14,7 +14,7 @@ describe('parser-consumes', () => { it('specifies swagger2', () => { - global.definition = require('../seeds/parserConsumesInitial.json') + globalThis.definition = require('../seeds/parserConsumesInitial.json') const consumes = require('../src/parser/swagger2/consumes.js')('POST','/pets') assert.equal(consumes, 'application/xml') @@ -22,7 +22,7 @@ describe('parser-consumes', () => { it('specifies openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json'); + globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json'); const consumes = require('../src/parser/openapi3/consumes.js')('POST','/pets'); assert.equal(consumes, 'application/json'); @@ -30,7 +30,7 @@ describe('parser-consumes', () => { it('specifies openapi3.1', () => { - global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json'); + globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json'); const consumes = require('../src/parser/openapi3/consumes.js')('POST','/pets'); assert.equal(consumes, 'application/json'); diff --git a/test/parser-endpoints.js b/test/parser-endpoints.js index 5bf03c7..b89e3aa 100644 --- a/test/parser-endpoints.js +++ b/test/parser-endpoints.js @@ -1,68 +1,70 @@ -/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ +/** Part of APIAddicts. See LICENSE file or full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ const assert = require('assert'); const sinon = require('sinon'); +const getEndpoints = require('../src/parser/endpoints.js'); describe('parser-endpoints', () => { - -before(() => { + + before(() => { sinon.stub(process, 'exit'); sinon.stub(console, 'log'); sinon.stub(console, 'error'); - }) + }); + + afterEach(() => { + process.exit.resetHistory(); + }); after(() => { process.exit.restore(); console.log.restore(); console.error.restore(); - }) - - it('endpoints bad swagger2', () => { - - global.definition = require('../seeds/parserEndpointsInitialBad.json'); - - require('../src/parser/endpoints.js')(); - - sinon.assert.called(process.exit); - sinon.assert.calledWith(process.exit, 1); - }) - - it('endpoints good swagger2', () => { - - global.definition = require('../seeds/parserEndpointsInitialGood.json'); - - const endpoints = require('../src/parser/endpoints.js')(); - assert.deepEqual(endpoints, [ - { verb: 'GET', path: '/pets' }, - { verb: 'POST', path: '/pets' }, - { verb: 'GET', path: '/pets/{id}' }, - { verb: 'DELETE', path: '/pets/{id}' } - ]) - }) - - it('endpoints good openapi3.0', () => { - - global.definition = require('../seeds/parserInitialGoodOpenApi3.json'); - - const endpoints = require('../src/parser/endpoints.js')(); - assert.deepEqual(endpoints, [ - { verb: 'GET', path: '/pets' }, - { verb: 'POST', path: '/pets' }, - { verb: 'GET', path: '/pets/{petId}' } - ]) - }) - - - it('endpoints good openapi3.1', () => { - - global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json'); - - const endpoints = require('../src/parser/endpoints.js')(); - assert.deepEqual(endpoints, [ - { verb: 'GET', path: '/pets' }, - { verb: 'POST', path: '/pets' }, - { verb: 'GET', path: '/pets/{petId}' } - ]) - }) - -}) \ No newline at end of file + }); + + const testCases = [ + { + name: 'endpoints bad swagger2', + seed: 'parserEndpointsInitialBad.json', + shouldExit: true + }, + { + name: 'endpoints good swagger2', + seed: 'parserEndpointsInitialGood.json', + expected: [ + { verb: 'GET', path: '/pets' }, { verb: 'POST', path: '/pets' }, + { verb: 'GET', path: '/pets/{id}' }, { verb: 'DELETE', path: '/pets/{id}' } + ] + }, + { + name: 'endpoints good openapi3.0', + seed: 'parserInitialGoodOpenApi3.json', + expected: [ + { verb: 'GET', path: '/pets' }, { verb: 'POST', path: '/pets' }, + { verb: 'GET', path: '/pets/{petId}' } + ] + }, + { + name: 'endpoints good openapi3.1', + seed: 'parserInitialGoodOpenApi3.1.json', + expected: [ + { verb: 'GET', path: '/pets' }, { verb: 'POST', path: '/pets' }, + { verb: 'GET', path: '/pets/{petId}' } + ] + } + ]; + + testCases.forEach(({ name, seed, expected, shouldExit }) => { + it(name, () => { + globalThis.definition = require(`../seeds/${seed}`); + const endpoints = getEndpoints(); + + if (shouldExit) { + sinon.assert.calledWith(process.exit, 1); + } else { + assert.deepEqual(endpoints, expected); + } + }); + }); + +}); \ No newline at end of file diff --git a/test/parser-microcks.js b/test/parser-microcks.js index 57febeb..edf57ce 100644 --- a/test/parser-microcks.js +++ b/test/parser-microcks.js @@ -7,7 +7,7 @@ describe('parser-microcks', () => { //If the document is not openapi3, it should return false because it is not supported it('specifies swagger2', () => { - global.definition = require('../seeds/parserMicroksInitial.json') + globalThis.definition = require('../seeds/parserMicroksInitial.json') const microcks = require('../src/parser/openapi3/microcks.js')('POST','/user') assert.equal(microcks, false) @@ -16,7 +16,7 @@ describe('parser-microcks', () => { //If the document is not openapi3, it should return false because it is not supported it('general swagger2', () => { - global.definition = require('../seeds/parserMicroksInitial.json') + globalThis.definition = require('../seeds/parserMicroksInitial.json') const microcks = require('../src/parser/openapi3/microcks.js')('GET','/user/{username}') assert.equal(microcks, false) @@ -25,7 +25,7 @@ describe('parser-microcks', () => { //If the document is openapi3, it should return true because it is supported it('specifies openapi3.0', () => { - global.definition = require('../seeds/parserMicroksinitialGood3.json'); + globalThis.definition = require('../seeds/parserMicroksinitialGood3.json'); const microcks = require('../src/parser/openapi3/microcks.js')('GET','/user/{username}'); assert.equal(microcks, true); @@ -33,7 +33,7 @@ describe('parser-microcks', () => { it('specifies openapi3.1', () => { - global.definition = require('../seeds/parserMicroksinitialGood3.1.json'); + globalThis.definition = require('../seeds/parserMicroksinitialGood3.1.json'); const microcks = require('../src/parser/openapi3/microcks.js')('GET','/user/{username}'); assert.equal(microcks, true); }) diff --git a/test/parser-pathParameters.js b/test/parser-pathParameters.js index 4ee5cb8..5a0dbee 100644 --- a/test/parser-pathParameters.js +++ b/test/parser-pathParameters.js @@ -6,7 +6,7 @@ describe('parser-pathParameters', () => { it('good swagger2', () => { - global.definition = require('../seeds/parserInitialGood.json') + globalThis.definition = require('../seeds/parserInitialGood.json') const pathParameters = require('../src/parser/swagger2/pathParameters.js')('DELETE','/pets/{id}') assert.deepStrictEqual(pathParameters, [ { name: 'id', type: 'integer', example: undefined } ]) @@ -14,7 +14,7 @@ describe('parser-pathParameters', () => { it('good openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.json') const status = require('../src/parser/openapi3/pathParameters.js')('GET','/pets/{petId}') assert.deepStrictEqual(status, [ { name: 'petId', type: 'string', example: 'asdf' } ]) @@ -22,7 +22,7 @@ describe('parser-pathParameters', () => { it('good openapi3.1', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') const status = require('../src/parser/openapi3/pathParameters.js')('GET','/pets/{petId}') assert.deepStrictEqual(status, [ { name: 'petId', type: 'string', example: 'asdf' } ]) diff --git a/test/parser-queryParams.js b/test/parser-queryParams.js index 21338ba..f38fc2f 100644 --- a/test/parser-queryParams.js +++ b/test/parser-queryParams.js @@ -3,79 +3,30 @@ const assert = require('assert'); describe('parser-queryParams', () => { - - it('queryParams fill swagger2', () => { - global.definition = require('../seeds/parserQueryParamsGood.json') + const testQuery = (name, parserPath, seed, method, path, expected) => { + it(name, () => { + globalThis.definition = require(`../seeds/${seed}`); + const queryParams = require(`../src/parser/${parserPath}/queryParams.js`)(method, path); + assert.deepStrictEqual(queryParams, expected); + }); + }; - const queryParams = require('../src/parser/swagger2/queryParams.js')('GET','/pets') - assert.deepStrictEqual(queryParams, [{ - "name": "tags", - "required": false, - "type": "array" - }, - { - "name": "limit", - "required": false, - "type": "integer" - } ]) - }) + const results = { + empty: [], + tagsLimit: (reqLimit) => [ + { "name": "tags", "required": false, "type": "array" }, + { "name": "limit", "required": reqLimit, "type": "integer" } + ] + }; - it('queryParams void swagger2', () => { + testQuery('queryParams fill swagger2', 'swagger2', 'parserQueryParamsGood.json', 'GET', '/pets', results.tagsLimit(false)); + testQuery('queryParams void swagger2', 'swagger2', 'parserQueryParamsGood.json', 'POST', '/pets', results.empty); - global.definition = require('../seeds/parserQueryParamsGood.json') + testQuery('queryParams fill openapi3.0', 'openapi3', 'parserInitialGoodOpenApiExpanded3.json', 'GET', '/pets', results.tagsLimit(true)); + testQuery('queryParams void openapi3.0', 'openapi3', 'parserInitialGoodOpenApiExpanded3.json', 'POST', '/pets', results.empty); - const queryParams = require('../src/parser/swagger2/queryParams.js')('POST','/pets') - assert.deepStrictEqual(queryParams, []) - }) + testQuery('queryParams fill openapi3.1', 'openapi3', 'parserInitialGoodOpenApiExpanded3.1.json', 'GET', '/pets', results.tagsLimit(true)); + testQuery('queryParams void openapi3.1', 'openapi3', 'parserInitialGoodOpenApiExpanded3.1.json', 'POST', '/pets', results.empty); - it('queryParams fill openapi3.0', () => { - - global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') - - const queryParams = require('../src/parser/openapi3/queryParams.js')('GET','/pets') - assert.deepStrictEqual(queryParams, [{ - "name": "tags", - "required": false, - "type": "array" - }, - { - "name": "limit", - "required": true, - "type": "integer" - } ]) - }) - - it('queryParams void openapi3.0', () => { - - global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') - - const queryParams = require('../src/parser/openapi3/queryParams.js')('POST','/pets') - assert.deepStrictEqual(queryParams, []) - }) - - it('queryParams fill openapi3.1', () => { - - global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') - - const queryParams = require('../src/parser/openapi3/queryParams.js')('GET','/pets') - assert.deepStrictEqual(queryParams, [{ - "name": "tags", - "required": false, - "type": "array" - }, - { - "name": "limit", - "required": true, - "type": "integer" - } ]) - }) - - it('queryParams void openapi3.1', () => { - - global.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') - - const queryParams = require('../src/parser/openapi3/queryParams.js')('POST','/pets') - assert.deepStrictEqual(queryParams, []) - }) -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/test/parser-schemaHostBasePath.js b/test/parser-schemaHostBasePath.js index 52876ba..073aad3 100644 --- a/test/parser-schemaHostBasePath.js +++ b/test/parser-schemaHostBasePath.js @@ -6,7 +6,7 @@ describe('parser-schemaHostBasePath', () => { it('good swagger2', () => { - global.definition = require('../seeds/parserSchemaHostBasePathInitialGood.json'); + globalThis.definition = require('../seeds/parserSchemaHostBasePathInitialGood.json'); const schemaHostBasePath = require('../src/parser/swagger2/schemaHostBasePath.js')(); assert.deepStrictEqual(schemaHostBasePath, { host: 'https://myserver.com', basePath: '/first/second' }); @@ -14,7 +14,7 @@ describe('parser-schemaHostBasePath', () => { it('good openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.json'); + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.json'); const schemaHostBasePath = require('../src/parser/openapi3/schemaHostBasePath.js')(); assert.deepStrictEqual(schemaHostBasePath, { host: 'http://petstore.swagger.io', basePath: '/v1' }); @@ -22,7 +22,7 @@ describe('parser-schemaHostBasePath', () => { it('good openapi3.1', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json'); + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.1.json'); const schemaHostBasePath = require('../src/parser/openapi3/schemaHostBasePath.js')(); assert.deepStrictEqual(schemaHostBasePath, { host: 'https://petstore.swagger.io', basePath: '/v1' }); diff --git a/test/parser-status.js b/test/parser-status.js index 17563d2..28b7009 100644 --- a/test/parser-status.js +++ b/test/parser-status.js @@ -6,7 +6,7 @@ describe('parser-status', () => { it('good swagger2', () => { - global.definition = require('../seeds/parserInitialGood.json') + globalThis.definition = require('../seeds/parserInitialGood.json') const status = require('../src/parser/status.js')('DELETE','/pets/{id}') assert.deepStrictEqual(status, [ 204, 500 ]) @@ -14,7 +14,7 @@ describe('parser-status', () => { it('good openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.json') const status = require('../src/parser/status.js')('POST','/pets') assert.deepStrictEqual(status, [ 201, 500 ]) @@ -22,7 +22,7 @@ describe('parser-status', () => { it('good openapi3.1', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') const status = require('../src/parser/status.js')('POST','/pets') assert.deepStrictEqual(status, [ 201, 500 ]) diff --git a/test/parser-summary.js b/test/parser-summary.js index e6eac16..4f6a74f 100644 --- a/test/parser-summary.js +++ b/test/parser-summary.js @@ -6,7 +6,7 @@ describe('parser-summary', () => { it('good swagger2', () => { - global.definition = require('../seeds/parserSummaryInitial.json') + globalThis.definition = require('../seeds/parserSummaryInitial.json') const summary = require('../src/parser/summary.js')('POST','/pets') assert.equal(summary, "Create a pet") @@ -14,7 +14,7 @@ describe('parser-summary', () => { it('good openapi3.0', () => { - global.definition = require('../seeds/parserSummaryOpenApi3.json') + globalThis.definition = require('../seeds/parserSummaryOpenApi3.json') const summary = require('../src/parser/summary.js')('POST','/pets') assert.equal(summary, "Create pet") @@ -22,7 +22,7 @@ describe('parser-summary', () => { it('good openapi3.1', () => { - global.definition = require('../seeds/parserSummaryOpenApi3.1.json') + globalThis.definition = require('../seeds/parserSummaryOpenApi3.1.json') const summary = require('../src/parser/summary.js')('POST','/pets') assert.equal(summary, "Create pet") diff --git a/test/parser-version.js b/test/parser-version.js index 2553f64..b466e06 100644 --- a/test/parser-version.js +++ b/test/parser-version.js @@ -6,7 +6,7 @@ describe('parser-version', () => { it('swagger2', () => { - global.definition = require('../seeds/parserInitialGood.json') + globalThis.definition = require('../seeds/parserInitialGood.json') const version = require('../src/parser/version.js')() assert.equal(version, 'swagger2') @@ -14,7 +14,7 @@ describe('parser-version', () => { it('openapi3.0', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.json') const version = require('../src/parser/version.js')() assert.equal(version, 'openapi3') @@ -22,7 +22,7 @@ describe('parser-version', () => { it('openapi version 3.0.2' , () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.0.2.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.0.2.json') const version = require('../src/parser/version.js')() assert.equal(version, 'openapi3') @@ -30,7 +30,7 @@ describe('parser-version', () => { it('openapi version 3.0.3' , () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.0.3.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.0.3.json') const version = require('../src/parser/version.js')() assert.equal(version, 'openapi3') @@ -38,7 +38,7 @@ describe('parser-version', () => { it('openapi3.1', () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') const version = require('../src/parser/version.js')() assert.equal(version, 'openapi3') @@ -46,7 +46,7 @@ describe('parser-version', () => { it('openapi version 3.1.1' , () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.1.1.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.1.1.json') const version = require('../src/parser/version.js')() assert.equal(version, 'openapi3') @@ -54,7 +54,7 @@ describe('parser-version', () => { it('openapi version 3.1.2' , () => { - global.definition = require('../seeds/parserInitialGoodOpenApi3.1.2.json') + globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.1.2.json') const version = require('../src/parser/version.js')() assert.equal(version, 'openapi3') From 924f703558d93e6df11a4ad08e3a0ef4fb4be93c Mon Sep 17 00:00:00 2001 From: Melsy Huamani Date: Thu, 5 Mar 2026 11:26:49 -0500 Subject: [PATCH 7/8] fix: sonar issues and tests --- seeds/parserEndpointsGoodOpenApi3Result.json | 5 + seeds/parserEndpointsGoodSwagger2Result.json | 6 + seeds/parserInitialGoodResultAllOfLoop.json | 17 +++ seeds/parserInitialGoodResultAllOfString.json | 6 + seeds/parserInitialGoodResultPetRequest.json | 8 ++ seeds/parserInitialGoodResultRespArray.json | 22 +++ seeds/parserInitialGoodResultRespObject.json | 19 +++ src/parser/openapi3/body.js | 4 +- src/parser/openapi3/consumes.js | 2 +- src/parser/openapi3/microcks.js | 2 +- src/parser/openapi3/queryParams.js | 51 ++----- src/parser/openapi3/refs.js | 24 ++-- src/parser/openapi3/schemaHostBasePath.js | 2 +- src/parser/swagger2/body.js | 7 +- src/parser/swagger2/queryParams.js | 30 ---- src/utils/circularRef.js | 45 +++--- test/parser-authorization.js | 26 ++-- test/parser-body.js | 130 ++++-------------- test/parser-endpoints.js | 49 ++----- 19 files changed, 191 insertions(+), 264 deletions(-) create mode 100644 seeds/parserEndpointsGoodOpenApi3Result.json create mode 100644 seeds/parserEndpointsGoodSwagger2Result.json create mode 100644 seeds/parserInitialGoodResultAllOfLoop.json create mode 100644 seeds/parserInitialGoodResultAllOfString.json create mode 100644 seeds/parserInitialGoodResultPetRequest.json create mode 100644 seeds/parserInitialGoodResultRespArray.json create mode 100644 seeds/parserInitialGoodResultRespObject.json diff --git a/seeds/parserEndpointsGoodOpenApi3Result.json b/seeds/parserEndpointsGoodOpenApi3Result.json new file mode 100644 index 0000000..0c20008 --- /dev/null +++ b/seeds/parserEndpointsGoodOpenApi3Result.json @@ -0,0 +1,5 @@ +[ + { "verb": "GET", "path": "/pets" }, + { "verb": "POST", "path": "/pets" }, + { "verb": "GET", "path": "/pets/{petId}" } +] \ No newline at end of file diff --git a/seeds/parserEndpointsGoodSwagger2Result.json b/seeds/parserEndpointsGoodSwagger2Result.json new file mode 100644 index 0000000..329c8cd --- /dev/null +++ b/seeds/parserEndpointsGoodSwagger2Result.json @@ -0,0 +1,6 @@ +[ + { "verb": "GET", "path": "/pets" }, + { "verb": "POST", "path": "/pets" }, + { "verb": "GET", "path": "/pets/{id}" }, + { "verb": "DELETE", "path": "/pets/{id}" } +] \ No newline at end of file diff --git a/seeds/parserInitialGoodResultAllOfLoop.json b/seeds/parserInitialGoodResultAllOfLoop.json new file mode 100644 index 0000000..edbdab3 --- /dev/null +++ b/seeds/parserInitialGoodResultAllOfLoop.json @@ -0,0 +1,17 @@ +{ + "type": "object", + "required": ["red", "orange"], + "properties": { + "red": { "type": "string", "maxLength": 50 }, + "orange": { "type": "number", "maxLength": 9 }, + "water": { + "type": "object", + "required": ["paramAiden"], + "properties": { + "paramAiden": { "type": "string" }, + "paramBiden": { "type": "string" }, + "paramCiden": { "type": "string" } + } + } + } +} \ No newline at end of file diff --git a/seeds/parserInitialGoodResultAllOfString.json b/seeds/parserInitialGoodResultAllOfString.json new file mode 100644 index 0000000..e39b116 --- /dev/null +++ b/seeds/parserInitialGoodResultAllOfString.json @@ -0,0 +1,6 @@ +{ + "type": "object", + "properties": { + "red": { "type": "string", "maxLength": 50 } + } +} \ No newline at end of file diff --git a/seeds/parserInitialGoodResultPetRequest.json b/seeds/parserInitialGoodResultPetRequest.json new file mode 100644 index 0000000..b7852ad --- /dev/null +++ b/seeds/parserInitialGoodResultPetRequest.json @@ -0,0 +1,8 @@ +{ + "type": "object", + "required": ["name"], + "properties": { + "name": { "type": "string" }, + "tag": { "type": "string" } + } +} \ No newline at end of file diff --git a/seeds/parserInitialGoodResultRespArray.json b/seeds/parserInitialGoodResultRespArray.json new file mode 100644 index 0000000..bff51d8 --- /dev/null +++ b/seeds/parserInitialGoodResultRespArray.json @@ -0,0 +1,22 @@ +{ + "200": { + "type": "array", + "items": { + "type": "object", + "required": ["name", "id"], + "properties": { + "name": { "type": "string" }, + "tag": { "type": "string" }, + "id": { "type": "integer", "format": "int64" } + } + } + }, + "500": { + "type": "object", + "required": ["code", "message"], + "properties": { + "code": { "type": "integer", "format": "int32" }, + "message": { "type": "string" } + } + } +} \ No newline at end of file diff --git a/seeds/parserInitialGoodResultRespObject.json b/seeds/parserInitialGoodResultRespObject.json new file mode 100644 index 0000000..48d8053 --- /dev/null +++ b/seeds/parserInitialGoodResultRespObject.json @@ -0,0 +1,19 @@ +{ + "200": { + "type": "object", + "required": ["name", "id"], + "properties": { + "name": { "type": "string" }, + "tag": { "type": "string" }, + "id": { "type": "integer", "format": "int64" } + } + }, + "500": { + "type": "object", + "required": ["code", "message"], + "properties": { + "code": { "type": "integer", "format": "int32" }, + "message": { "type": "string" } + } + } +} \ No newline at end of file diff --git a/src/parser/openapi3/body.js b/src/parser/openapi3/body.js index d418935..db696f6 100644 --- a/src/parser/openapi3/body.js +++ b/src/parser/openapi3/body.js @@ -34,7 +34,7 @@ module.exports = function () { } if (!body.content['application/json']) { const contentsArray = Object.keys(body.content); - let schema = undefined; + let schema; let properContent = false; let index = 0; while (!properContent && index < contentsArray.length) { @@ -85,7 +85,7 @@ module.exports = function () { } const bodyResponses = {} _.forEach(endpoint['responses'], function (response, status) { - if (response && response.content && response.content['application/json'] && response.content['application/json'].schema) { + if (response?.content?.['application/json']?.schema) { const withOutRefs = replaceRefs(response.content['application/json'].schema, 1) bodyResponses[status] = replaceAllOfs(withOutRefs) if (bodyResponses[status].hasOwnProperty('required')) { diff --git a/src/parser/openapi3/consumes.js b/src/parser/openapi3/consumes.js index 2f5aa5b..4499c66 100644 --- a/src/parser/openapi3/consumes.js +++ b/src/parser/openapi3/consumes.js @@ -16,7 +16,7 @@ module.exports = function () { } const request = globalThis.definition.paths[path][_.toLower(verb)] - if (request.requestBody && request.requestBody.content) { + if (request.requestBody?.content) { return _.keys(request.requestBody.content)[0] } return 'application/json'; diff --git a/src/parser/openapi3/microcks.js b/src/parser/openapi3/microcks.js index 7660d81..aa12e65 100644 --- a/src/parser/openapi3/microcks.js +++ b/src/parser/openapi3/microcks.js @@ -1,6 +1,6 @@ const _ = require('lodash'); -module.exports = (function (verb, path) { +module.exports = (function hasMicrocksOperation(verb, path) { const hasPaths = _.isObject(globalThis.definition.paths); const hasWebhooks = _.isObject(globalThis.definition.webhooks); diff --git a/src/parser/openapi3/queryParams.js b/src/parser/openapi3/queryParams.js index 6640fcf..650c2df 100644 --- a/src/parser/openapi3/queryParams.js +++ b/src/parser/openapi3/queryParams.js @@ -6,12 +6,9 @@ const _ = require('lodash'); module.exports = function() { - return function get(verb,path){ - if (!_.isObject(globalThis.definition.paths)) { - } + return function get(verb,path){ let parameters = globalThis.definition.paths[path][_.toLower(verb)]['parameters']; - // parameters = replaceRefs(parameters); let queryParams = _.filter(parameters, ['in', 'query']) const result = [] _.forEach(queryParams, function(queryParam) { @@ -35,36 +32,6 @@ module.exports = function() { return result }; - function replaceRefs(schema){ - let result = {} - for (let i in schema) { - if (i === '$ref'){ - const ref = _.replace(schema[i], '#/components/parameters/', ''); - const schemaRef = _.replace(schema[i], '#/components/schemas/', ''); - let entity = globalThis.definition.components.parameters[ref] || globalThis.definition.components.schemas[schemaRef]; - if (!entity){ - require('../../utils/error.js')('ref '+ref+' is not defined') - } - entity = replaceRefs(entity,globalThis.definition) - result = _.merge(result, entity) - } else if ( _.isArray(schema[i]) && i !== 'required'){ - const arrayResult = [] - if (i === 'example'){ - continue; - } - for (let k in schema[i]) { - arrayResult.push(replaceRefs(schema[i][k],globalThis.definition)) - } - result[i] = arrayResult - } else if ( _.isObject(schema[i]) && i !== 'required'){ - result[i] = replaceRefs(schema[i],globalThis.definition) - } else { - result[i] = schema[i]; - } - } - return result; - } - function getExamples(queryParam) { if (!queryParam?.schema) return undefined; @@ -72,9 +39,9 @@ module.exports = function() { return queryParam.example; } - if (queryParam.schema?.examples) { - return queryParam.schema.examples[0]; - } + if (queryParam.schema?.examples) { + return queryParam.schema.examples[0]; + } if (queryParam.hasOwnProperty('examples')) { const firstKey = Object.keys(queryParam.examples)[0]; @@ -85,14 +52,16 @@ module.exports = function() { return value; } - return queryParam.example !== undefined ? queryParam.example : queryParam.schema.example; + if (queryParam.example === undefined) { + return queryParam.schema.example; + } + + return queryParam.example; } function getContentProperty(query){ const queryContent = query.content; - for (const key in queryContent) { - return queryContent[key]; - } + return queryContent ? Object.values(queryContent)[0] : undefined; } }() \ No newline at end of file diff --git a/src/parser/openapi3/refs.js b/src/parser/openapi3/refs.js index 8f4cbc3..8029f0e 100644 --- a/src/parser/openapi3/refs.js +++ b/src/parser/openapi3/refs.js @@ -3,20 +3,16 @@ 'use strict' function eachRecursive(obj) { - for (var k in obj) { + for (let k in obj) { if (typeof obj[k] == "object" && obj[k] !== null) { eachRecursive(obj[k]); - } else { - if (k == '$ref') { - let property = obj[k] - property = property.replace('#/', '') - let propertiesArray = property.split('/') - let refObject = findObject(global.definition, propertiesArray) - // Clear ref property - delete obj[k] - // Assign properties refOcject - Object.assign(obj, refObject) - } + } else if (k == '$ref') { + let property = obj[k] + property = property.replace('#/', '') + let propertiesArray = property.split('/') + let refObject = findObject(globalThis.definition, propertiesArray) + delete obj[k] + Object.assign(obj, refObject) } } } @@ -32,7 +28,7 @@ function findObject(obj, propertiesArray) { module.exports = function() { return function get() { - eachRecursive(global.definition) - return global.definition + eachRecursive(globalThis.definition) + return globalThis.definition } }() \ No newline at end of file diff --git a/src/parser/openapi3/schemaHostBasePath.js b/src/parser/openapi3/schemaHostBasePath.js index 3d2fc8e..a8d14c7 100644 --- a/src/parser/openapi3/schemaHostBasePath.js +++ b/src/parser/openapi3/schemaHostBasePath.js @@ -7,7 +7,7 @@ const _ = require('lodash'); module.exports = function() { return function get(){ - if (!globalThis.definition.servers || !_.isArray(globalThis.definition.servers) || !globalThis.definition.servers[0] || !globalThis.definition.servers[0].url || !_.isString(globalThis.definition.servers[0].url)) { + if (!globalThis.definition.servers || !_.isArray(globalThis.definition.servers) || !globalThis.definition.servers[0]?.url || !_.isString(globalThis.definition.servers[0].url)) { require('../../utils/error.js')('servers is required') } const all = globalThis.definition.servers[0].url diff --git a/src/parser/swagger2/body.js b/src/parser/swagger2/body.js index 0466871..bd4370e 100644 --- a/src/parser/swagger2/body.js +++ b/src/parser/swagger2/body.js @@ -70,7 +70,7 @@ module.exports = function() { require('../../utils/error.js')('ref ' + ref + ' is not defined'); } } - entity = replaceRefs(entity, globalThis.definition); + entity = replaceRefs(entity); result = _.merge(result, entity); } else if ( _.isArray(schema[i]) && i !== 'required'){ const arrayResult = []; @@ -78,11 +78,11 @@ module.exports = function() { continue; } for (let k in schema[i]) { - arrayResult.push(replaceRefs(schema[i][k],globalThis.definition)); + arrayResult.push(replaceRefs(schema[i][k])); } result[i] = arrayResult; } else if ( _.isObject(schema[i]) && i !== 'required'){ - result[i] = replaceRefs(schema[i],globalThis.definition); + result[i] = replaceRefs(schema[i]); } else { result[i] = schema[i]; } @@ -100,7 +100,6 @@ module.exports = function() { if (schema[i][t]['type'] === 'string') { merged = schema[i][t]; } else { - for (let k in schema[i][t]) { if (k === 'type'){ merged['type'] = schema[i][t][k]; diff --git a/src/parser/swagger2/queryParams.js b/src/parser/swagger2/queryParams.js index d319434..5a2fa4f 100644 --- a/src/parser/swagger2/queryParams.js +++ b/src/parser/swagger2/queryParams.js @@ -12,7 +12,6 @@ module.exports = function() { } let parameters = globalThis.definition.paths[path][_.toLower(verb)]['parameters']; - // parameters = replaceRefs(parameters); const queryParams = _.filter(parameters, ['in', 'query']) const result = [] _.forEach(queryParams, function(queryParam) { @@ -33,35 +32,6 @@ module.exports = function() { return result; }; - function replaceRefs(schema){ - let result = {}; - for (let i in schema) { - if (i === '$ref'){ - const ref = _.replace(schema[i], '#/parameters/', ''); - let entity = globalThis.definition.parameters[ref]; - if (!entity){ - continue; - } - entity = replaceRefs(entity, globalThis.definition); - result = _.merge(result, entity); - } else if (_.isArray(schema[i]) && i !== 'required'){ - const arrayResult = []; - if (i === 'example'){ - continue; - } - for (let k in schema[i]) { - arrayResult.push(replaceRefs(schema[i][k],globalThis.definition)); - } - result[i] = arrayResult; - } else if (_.isObject(schema[i]) && i !== 'required'){ - result[i] = replaceRefs(schema[i],globalThis.definition); - } else { - result[i] = schema[i]; - } - } - return result; - } - function getExamples(queryParam) { if (queryParam.hasOwnProperty('example')) { return queryParam.example; diff --git a/src/utils/circularRef.js b/src/utils/circularRef.js index 031c820..a1179b1 100644 --- a/src/utils/circularRef.js +++ b/src/utils/circularRef.js @@ -6,27 +6,38 @@ const _ = require('lodash'); module.exports = function checkCircularReferences(reference, depthLevel, patternNumber) { - const tail = globalThis.circularTail = globalThis.circularTail || []; - - if (!tail[patternNumber]) { - tail[patternNumber] = [reference]; - return false; + if (!globalThis.circularTail) { + globalThis.circularTail = [] + } + if (!globalThis.circularTail[patternNumber]) { + globalThis.circularTail[patternNumber] = [reference] + return false + } + if (globalThis.circularTail[patternNumber].length < (depthLevel * patternNumber)) { + globalThis.circularTail[patternNumber].push(reference) + return false } - const currentPattern = tail[patternNumber]; + const groups = _.chunk(globalThis.circularTail[patternNumber], patternNumber) + globalThis.circularTail[patternNumber].shift() + globalThis.circularTail[patternNumber].push(reference) - if (currentPattern.length < (depthLevel * patternNumber)) { - currentPattern.push(reference); - return false; - } + let areEquals = true - currentPattern.shift(); - currentPattern.push(reference); + for (let i = 1; i < groups.length; i++) { + for (let k in groups[i]) { + if (groups[i][k] !== groups[i - 1][k]) { + areEquals = false + break + } + } + if (!areEquals) break + } - const groups = _.chunk(currentPattern, patternNumber); - const areEquals = groups.length > 1 && groups.every(group => _.isEqual(group, groups[0])); + if (areEquals) { + globalThis.circularTail = [] + } - if (areEquals) globalThis.circularTail = []; + return areEquals - return areEquals; -}; \ No newline at end of file +} \ No newline at end of file diff --git a/test/parser-authorization.js b/test/parser-authorization.js index 5152b54..6c81a19 100644 --- a/test/parser-authorization.js +++ b/test/parser-authorization.js @@ -1,26 +1,26 @@ /** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ -const assert = require('assert'); +const assert = require('node:assert'); const getAuthorization = require('../src/parser/authorization.js'); describe('parser-authorization', () => { - const testCases = [ - { name: 'authorization good swagger2', seed: 'parserAuthorizationInitial.json', method: 'POST', path: '/apple', expected: 'user_token' }, - { name: 'authorization endpoint swagger2', seed: 'parserAuthorizationInitialEndpoint.json', method: 'POST', path: '/apple', expected: 'OAuth2' }, - { name: 'authorization general swagger2', seed: 'parserAuthorizationInitialGeneral.json', method: 'POST', path: '/apple', expected: 'BasicAuth' }, - { name: 'authorization general openapi3.0', seed: 'parserAuthorizationInitialOpenApi3.json', method: 'POST', path: '/pets', expected: 'ApiKeyAuth' }, - { name: 'authorization endpoint openapi3.0', seed: 'parserAuthorizationInitialOpenApi3.json', method: 'GET', path: '/pets', expected: 'OAuth2' }, - { name: 'authorization general openapi3.1', seed: 'parserAuthorizationInitialOpenApi3.1.json', method: 'POST', path: '/pets', expected: 'ApiKeyAuth' }, - { name: 'authorization endpoint openapi3.1', seed: 'parserAuthorizationInitialOpenApi3.1.json', method: 'GET', path: '/pets', expected: 'OAuth2' } - ]; - - testCases.forEach(({ name, seed, method, path, expected }) => { + const checkAuth = (name, seed, method, path, expected) => { it(name, () => { globalThis.definition = require(`../seeds/${seed}`); const authorization = getAuthorization(method, path); assert.deepStrictEqual(authorization, expected); }); - }); + }; + + checkAuth('auth good sw2', 'parserAuthorizationInitial.json', 'POST', '/apple', 'user_token'); + checkAuth('auth endpoint sw2', 'parserAuthorizationInitialEndpoint.json', 'POST', '/apple', 'OAuth2'); + checkAuth('auth general sw2', 'parserAuthorizationInitialGeneral.json', 'POST', '/apple', 'BasicAuth'); + + checkAuth('auth general oa3.0','parserAuthorizationInitialOpenApi3.json', 'POST', '/pets', 'ApiKeyAuth'); + checkAuth('auth endpoint oa3.0','parserAuthorizationInitialOpenApi3.json', 'GET', '/pets', 'OAuth2'); + + checkAuth('auth general oa3.1', 'parserAuthorizationInitialOpenApi3.1.json','POST', '/pets', 'ApiKeyAuth'); + checkAuth('auth endpoint oa3.1', 'parserAuthorizationInitialOpenApi3.1.json','GET', '/pets', 'OAuth2'); }); \ No newline at end of file diff --git a/test/parser-body.js b/test/parser-body.js index 4aa1380..026d338 100644 --- a/test/parser-body.js +++ b/test/parser-body.js @@ -1,130 +1,52 @@ /** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ -const assert = require('assert') +const assert = require('node:assert'); describe('parser-body', () => { + const checkBody = (name, parser, seed, method, path, isResp, expectedFile) => { + it(name, () => { + globalThis.definition = require(`../seeds/${seed}`); - it('body void request swagger2', () => { + if (isResp) globalThis.circularTail = []; - globalThis.definition = require('../seeds/parserInitialGood.json') + const expected = expectedFile ? require(`../seeds/${expectedFile}`) : undefined; + const body = require(`../src/parser/${parser}/body.js`)(method, path, isResp); - const body = require('../src/parser/swagger2/body.js')('GET','/pets') - assert.deepStrictEqual(body, undefined) - }) + assert.deepStrictEqual(body, expected); + }); + }; - it('body void request openapi3.0', () => { + checkBody('body void request swagger2','swagger2','parserInitialGood.json','GET','/pets',false,null); - globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.json') + checkBody('body void request openapi3.0','openapi3','parserInitialGoodOpenApi3.json','GET','/pets',false,null); - const body = require('../src/parser/openapi3/body.js')('GET','/pets') - assert.deepStrictEqual(body, undefined) - }) + checkBody('body void request openapi3.0 2','openapi3','parserInitialGoodOpenApi3.json','POST','/pets',false,null); - it('body void request openapi3.0 2', () => { + checkBody('body void request openapi3.1','openapi3','parserInitialGoodOpenApi3.1.json','GET','/pets',false,null); - globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.json') - const body = require('../src/parser/openapi3/body.js')('POST','/pets') - assert.deepStrictEqual(body, undefined) - }) + checkBody('body fill request swagger2','swagger2','parserInitialGood.json','POST','/pets',false,'parserInitialGoodResultPetRequest.json'); - it('body void request openapi3.1', () => { + checkBody('body fill request openapi3.0','openapi3','parserInitialGoodOpenApiExpanded3.json','POST','/pets',false,'parserInitialGoodResultPetRequest.json'); - globalThis.definition = require('../seeds/parserInitialGoodOpenApi3.1.json') + checkBody('body fill request openapi3.1','openapi3','parserInitialGoodOpenApiExpanded3.1.json','POST','/pets',false,'parserInitialGoodResultPetRequest.json'); - const body = require('../src/parser/openapi3/body.js')('GET','/pets') - assert.deepStrictEqual(body, undefined) - }) - it('body fill request swagger2', () => { + checkBody('body items,ref and allof response swagger2','swagger2','parserInitialGood.json','GET','/pets',true,'parserInitialGoodResultRespArray.json'); - globalThis.definition = require('../seeds/parserInitialGood.json') + checkBody('body items,ref and allof response openapi3.0','openapi3','parserInitialGoodOpenApiExpanded3.json','GET','/pets',true,'parserInitialGoodResultRespArray.json'); - const body = require('../src/parser/swagger2/body.js')('POST','/pets') - assert.deepStrictEqual(body, {"type":"object","required":["name"],"properties":{"name":{"type":"string"},"tag":{"type":"string"}}}) - }) + checkBody('body items,ref and allof response openapi3.1','openapi3','parserInitialGoodOpenApiExpanded3.1.json','GET','/pets',true,'parserInitialGoodResultRespArray.json'); - it('body fill request openapi3.0', () => { - globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') + checkBody('body ref and allof response swagger2','swagger2','parserInitialGood.json','POST','/pets',true,'parserInitialGoodResultRespObject.json'); - const body = require('../src/parser/openapi3/body.js')('POST','/pets') - assert.deepStrictEqual(body, {"type":"object","required":["name"],"properties":{"name":{"type":"string"},"tag":{"type":"string"}}}) - }) + checkBody('body ref and allof response openapi3.0','openapi3','parserInitialGoodOpenApiExpanded3.json','POST','/pets',true,'parserInitialGoodResultRespObject.json'); - it('body fill request openapi3.1', () => { + checkBody('body ref and allof response openapi3.1','openapi3','parserInitialGoodOpenApiExpanded3.1.json','POST','/pets',true,'parserInitialGoodResultRespObject.json'); - globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') - const body = require('../src/parser/openapi3/body.js')('POST','/pets') - assert.deepStrictEqual(body, {"type":"object","required":["name"],"properties":{"name":{"type":"string"},"tag":{"type":"string"}}}) - }) + checkBody('body allof loop swagger2','swagger2','parserBodyAllofLoopInitial.json','POST','/apple',false,'parserInitialGoodResultAllOfLoop.json'); - it('body items, ref and allof response swagger2', () => { - - globalThis.definition = require('../seeds/parserInitialGood.json') - - const body = require('../src/parser/swagger2/body.js')('GET','/pets',true) - assert.deepStrictEqual(body, {"200":{"type":"array","items":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) - }) - - it('body items, ref and allof response openapi3.0', () => { - - globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') - - const body = require('../src/parser/openapi3/body.js')('GET','/pets',true) - assert.deepStrictEqual(body, {"200":{"type":"array","items":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) - }) - - it('body items, ref and allof response openapi3.1', () => { - - globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') - - const body = require('../src/parser/openapi3/body.js')('GET','/pets',true) - assert.deepStrictEqual(body, {"200":{"type":"array","items":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) - }) - - it('body ref and allof response swagger2', () => { - - globalThis.definition = require('../seeds/parserInitialGood.json') - globalThis.circularTail = [] - - const body = require('../src/parser/swagger2/body.js')('POST','/pets',true) - assert.deepStrictEqual(body, {"200":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) - }) - - it('body ref and allof response openapi3.0', () => { - - globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.json') - globalThis.circularTail = [] - - const body = require('../src/parser/openapi3/body.js')('POST','/pets',true) - assert.deepStrictEqual(body, {"200":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) - }) - - it('body ref and allof response openapi3.1', () => { - - globalThis.definition = require('../seeds/parserInitialGoodOpenApiExpanded3.1.json') - globalThis.circularTail = [] - - const body = require('../src/parser/openapi3/body.js')('POST','/pets',true) - assert.deepStrictEqual(body, {"200":{"type":"object","required":["name","id"],"properties":{"name":{"type":"string"},"tag":{"type":"string"},"id":{"type":"integer","format":"int64"}}},"500":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}) - }) - - it('body allof loop swagger2', () => { - - globalThis.definition = require('../seeds/parserBodyAllofLoopInitial.json') - - const body = require('../src/parser/swagger2/body.js')('POST','/apple') - assert.deepStrictEqual(body, {"required":["red","orange"],"properties":{"red":{"type":"string","maxLength":50},"orange":{"type":"number","maxLength":9},"water":{"required":["paramAiden"],"properties":{"paramAiden":{"type":"string"},"paramBiden":{"type":"string"},"paramCiden":{"type":"string"}},"type":"object"}},"type":"object"}) - }) - - it('body allof string swagger2', () => { - - globalThis.definition = require('../seeds/parserBodyAllofString.json') - - const body = require('../src/parser/swagger2/body.js')('POST','/apple') - assert.deepStrictEqual(body, {"type":"object","properties":{"red":{"type":"string","maxLength":50}}}) - }) - -}) \ No newline at end of file + checkBody('body allof string swagger2','swagger2','parserBodyAllofString.json','POST','/apple',false,'parserInitialGoodResultAllOfString.json'); +}); \ No newline at end of file diff --git a/test/parser-endpoints.js b/test/parser-endpoints.js index b89e3aa..7085240 100644 --- a/test/parser-endpoints.js +++ b/test/parser-endpoints.js @@ -1,6 +1,6 @@ /** Part of APIAddicts. See LICENSE file or full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ -const assert = require('assert'); +const assert = require('node:assert'); const sinon = require('sinon'); const getEndpoints = require('../src/parser/endpoints.js'); @@ -22,39 +22,7 @@ describe('parser-endpoints', () => { console.error.restore(); }); - const testCases = [ - { - name: 'endpoints bad swagger2', - seed: 'parserEndpointsInitialBad.json', - shouldExit: true - }, - { - name: 'endpoints good swagger2', - seed: 'parserEndpointsInitialGood.json', - expected: [ - { verb: 'GET', path: '/pets' }, { verb: 'POST', path: '/pets' }, - { verb: 'GET', path: '/pets/{id}' }, { verb: 'DELETE', path: '/pets/{id}' } - ] - }, - { - name: 'endpoints good openapi3.0', - seed: 'parserInitialGoodOpenApi3.json', - expected: [ - { verb: 'GET', path: '/pets' }, { verb: 'POST', path: '/pets' }, - { verb: 'GET', path: '/pets/{petId}' } - ] - }, - { - name: 'endpoints good openapi3.1', - seed: 'parserInitialGoodOpenApi3.1.json', - expected: [ - { verb: 'GET', path: '/pets' }, { verb: 'POST', path: '/pets' }, - { verb: 'GET', path: '/pets/{petId}' } - ] - } - ]; - - testCases.forEach(({ name, seed, expected, shouldExit }) => { + const checkEndpoints = (name, seed, expectedFile, shouldExit = false) => { it(name, () => { globalThis.definition = require(`../seeds/${seed}`); const endpoints = getEndpoints(); @@ -62,9 +30,18 @@ describe('parser-endpoints', () => { if (shouldExit) { sinon.assert.calledWith(process.exit, 1); } else { - assert.deepEqual(endpoints, expected); + const expected = require(`../seeds/${expectedFile}`); + assert.deepStrictEqual(endpoints, expected); } }); - }); + }; + + checkEndpoints('endpoints bad swagger2', 'parserEndpointsInitialBad.json', null, true); + + checkEndpoints('endpoints good swagger2', 'parserEndpointsInitialGood.json', 'parserEndpointsGoodSwagger2Result.json'); + + checkEndpoints('endpoints good openapi3.0', 'parserInitialGoodOpenApi3.json', 'parserEndpointsGoodOpenApi3Result.json'); + + checkEndpoints('endpoints good openapi3.1', 'parserInitialGoodOpenApi3.1.json', 'parserEndpointsGoodOpenApi3Result.json'); }); \ No newline at end of file From 8723310d4aa14cb59a6863cee9cc413506271502 Mon Sep 17 00:00:00 2001 From: Melsy Huamani Date: Thu, 5 Mar 2026 12:20:34 -0500 Subject: [PATCH 8/8] update changelog 2.3.0 --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 258e233..0cfe457 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2.1.0] - 2024-10-8 +## [2.3.0] - 2026-03-05 + +### Added +- Added support for OpenAPI 3.1. + +## [2.1.0] - 2024-10-08 ## Added