diff --git a/CHANGELOG.md b/CHANGELOG.md index 74acfc9..c778cb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2.4.1-beta-1] - 2026-06-26 ### Fixed +- Fix schema validation crash on 204 No Content endpoints when `validate_schema: true`. - Resolve external `$ref` (HTTP/HTTPS URLs) instead of crashing with `TypeError`. External schemas are fetched, cached, and inlined at parse time using Node's built-in `http`/`https` modules. diff --git a/seeds/generatorTestBody204Initial.json b/seeds/generatorTestBody204Initial.json new file mode 100644 index 0000000..84cb643 --- /dev/null +++ b/seeds/generatorTestBody204Initial.json @@ -0,0 +1,43 @@ +{ + "name": "/pets/{id}-204", + "aux": { + "status": "204", + "body": false, + "consumes": false, + "bodyResponse": { + "500": { + "type": "object", + "required": ["code", "message"], + "properties": { + "code": { "type": "integer", "format": "int32" }, + "message": { "type": "string" } + } + } + } + }, + "response": [], + "request": { + "method": "DELETE", + "header": [], + "body": { "mode": "raw", "raw": "" }, + "url": { + "raw": "{{host}}{{port}}{{basePath}}/pets/{{id}}", + "host": ["{{host}}{{port}}{{basePath}}"], + "path": ["/pets/{{id}}"] + } + }, + "event": [ + { + "listen": "test", + "script": { + "id": "test-204-uuid", + "type": "text/javascript", + "exec": [ + "pm.test(\"Status code is 204\", function () {", + " pm.response.to.have.status(204);", + "});" + ] + } + } + ] +} diff --git a/seeds/generatorTestBody204Result.json b/seeds/generatorTestBody204Result.json new file mode 100644 index 0000000..84cb643 --- /dev/null +++ b/seeds/generatorTestBody204Result.json @@ -0,0 +1,43 @@ +{ + "name": "/pets/{id}-204", + "aux": { + "status": "204", + "body": false, + "consumes": false, + "bodyResponse": { + "500": { + "type": "object", + "required": ["code", "message"], + "properties": { + "code": { "type": "integer", "format": "int32" }, + "message": { "type": "string" } + } + } + } + }, + "response": [], + "request": { + "method": "DELETE", + "header": [], + "body": { "mode": "raw", "raw": "" }, + "url": { + "raw": "{{host}}{{port}}{{basePath}}/pets/{{id}}", + "host": ["{{host}}{{port}}{{basePath}}"], + "path": ["/pets/{{id}}"] + } + }, + "event": [ + { + "listen": "test", + "script": { + "id": "test-204-uuid", + "type": "text/javascript", + "exec": [ + "pm.test(\"Status code is 204\", function () {", + " pm.response.to.have.status(204);", + "});" + ] + } + } + ] +} diff --git a/src/generator/environmentVariablesNames.js b/src/generator/environmentVariablesNames.js index 4fdb0ae..c4337c0 100644 --- a/src/generator/environmentVariablesNames.js +++ b/src/generator/environmentVariablesNames.js @@ -140,6 +140,7 @@ module.exports = function() { } function extractVariablesFromTest(aux, execCode, numerateItem, items){ if (global.configurationFile.schema_is_inline === false) { + if (!aux.bodyResponse?.[aux.status]) return; const key = numerateItem + 'schemaTest'; for (let i in execCode){ if (execCode[i] === 'var schema = pm.environment.get("schemaTest");'){ diff --git a/src/generator/testBody.js b/src/generator/testBody.js index 28544a4..26133b0 100644 --- a/src/generator/testBody.js +++ b/src/generator/testBody.js @@ -9,13 +9,16 @@ module.exports = function() { return function get(postmanRequest, configurationFile) { - if ((!postmanRequest.aux.bodyResponse || !postmanRequest.aux.bodyResponse[postmanRequest.aux.status]) && postmanRequest.aux.status === 200) { - console.warn( - '\x1b[33m%s\x1b[0m', - `Test: ${postmanRequest.request.method} ${postmanRequest.name} (${postmanRequest.aux.suffix === undefined ? 'main test' : postmanRequest.aux.suffix.trim()}) without schema validation test because it has a different response than 'application/json'` + if (!postmanRequest.aux.bodyResponse || !postmanRequest.aux.bodyResponse[postmanRequest.aux.status]) { + const noBodyStatuses = ['204', '205', '304']; + if (!noBodyStatuses.includes(String(postmanRequest.aux.status))) { + console.warn( + '\x1b[33m%s\x1b[0m', + `Test: ${postmanRequest.request.method} ${postmanRequest.name} (${postmanRequest.aux.suffix === undefined ? 'main test' : postmanRequest.aux.suffix.trim()}) without schema validation test because it has a different response than 'application/json'` ); + } return postmanRequest; - } + } let schemaJSON; if (configurationFile.schema_is_inline === false) { diff --git a/test/generator-envVariables.js b/test/generator-envVariables.js new file mode 100644 index 0000000..c6674e3 --- /dev/null +++ b/test/generator-envVariables.js @@ -0,0 +1,84 @@ +/** Part of APIAddicts. See LICENSE fileor full copyright and licensing details. Supported by Madrid Digital and CloudAPPi **/ + +const assert = require('node:assert'); + +describe('generator-envVariables', () => { + + let savedConfig; + let savedEnvVars; + + beforeEach(() => { + savedConfig = globalThis.configurationFile; + savedEnvVars = globalThis.environmentVariables; + globalThis.environmentVariables = {}; + }); + + afterEach(() => { + globalThis.configurationFile = savedConfig; + globalThis.environmentVariables = savedEnvVars; + }); + + it('204 no body schema is inline false', () => { + globalThis.configurationFile = { schema_is_inline: false, schema_pretty_print: false, is_inline: false }; + + const collection = [ + { + name: 'pets', + item: [ + { + name: 'pets', + item: [ + { + name: '/pets/{id}-204', + aux: { + numerateItem: '1', + status: '204', + bodyResponse: { + '500': { + type: 'object', + required: ['code', 'message'], + properties: { + code: { type: 'integer', format: 'int32' }, + message: { type: 'string' } + } + } + }, + queryParams: [] + }, + request: { + method: 'DELETE', + header: [], + body: { mode: 'raw', raw: '' }, + url: { + raw: '{{host}}{{port}}{{basePath}}/pets/1', + host: ['{{host}}{{port}}{{basePath}}'], + path: ['/pets/1'] + } + }, + event: [ + { + listen: 'test', + script: { + id: 'test-204-uuid', + type: 'text/javascript', + exec: [ + 'pm.test("Status code is 204", function () {', + ' pm.response.to.have.status(204);', + '});' + ] + } + } + ] + } + ] + } + ] + } + ]; + + const items = require('../src/generator/environmentVariablesNames.js')(collection); + const schemaTestItem = items.find(item => item.key?.includes('schemaTest')); + assert.strictEqual(schemaTestItem, undefined, 'No schemaTest env variable should be created for 204 No Content'); + }); + +}); diff --git a/test/generator-testBody.js b/test/generator-testBody.js index a6a0246..5c6d6ee 100644 --- a/test/generator-testBody.js +++ b/test/generator-testBody.js @@ -13,4 +13,13 @@ describe('generator-testBody', () => { assert.deepStrictEqual(definition, definitionResult); }); + it('204 no body', () => { + + const definitionInitial = require('../seeds/generatorTestBody204Initial.json'); + const definitionResult = require('../seeds/generatorTestBody204Result.json'); + + const definition = require('../src/generator/testBody.js')(definitionInitial, {schema_pretty_print: false}); + assert.deepStrictEqual(definition, definitionResult); + }); + }); \ No newline at end of file