From bc7d98d8c98cdba43ec5b59bb656dc715aceafd7 Mon Sep 17 00:00:00 2001 From: Prasanth Janardhanan Date: Fri, 13 Feb 2026 13:03:05 +0530 Subject: [PATCH] Fixes issue 57: Empty object schemas were incorrectly flagged as incomplete --- functions/completedSchema.js | 8 +- functions/completedSchema.spec.js | 84 +++++++++++++++++++ .../general-schema-definition/positive.json | 21 +++++ 3 files changed, 112 insertions(+), 1 deletion(-) diff --git a/functions/completedSchema.js b/functions/completedSchema.js index 3bc80c8..f8378d9 100644 --- a/functions/completedSchema.js +++ b/functions/completedSchema.js @@ -24,7 +24,7 @@ * @param {Options} opts String requirements given by the linter ruleset */ export default function (targetVal) { - if (typeof targetVal !== 'object') { + if (targetVal == null || typeof targetVal !== 'object') { return; } @@ -41,6 +41,12 @@ export default function (targetVal) { return; } + // An object with additionalProperties: false and no properties is a valid + // schema representing an intentionally empty object (e.g., {}) + if (targetVal.additionalProperties === false) { + return; + } + return [ { message: 'properties missing for object schema', diff --git a/functions/completedSchema.spec.js b/functions/completedSchema.spec.js index efeedee..f8a955c 100644 --- a/functions/completedSchema.spec.js +++ b/functions/completedSchema.spec.js @@ -87,4 +87,88 @@ describe('completedSchema', () => { }, ]); }); + + describe('additionalProperties: false (Issue #57)', () => { + test('should pass for empty object with additionalProperties: false', () => { + const schema = { + type: 'object', + additionalProperties: false, + }; + expect(completedSchema(schema)).toBeUndefined(); + }); + + test('should pass for empty object with additionalProperties: false and description', () => { + const schema = { + type: 'object', + description: 'Response for successful operation', + additionalProperties: false, + }; + expect(completedSchema(schema)).toBeUndefined(); + }); + + test('should pass for empty object with additionalProperties: false and example', () => { + const schema = { + type: 'object', + example: {}, + additionalProperties: false, + }; + expect(completedSchema(schema)).toBeUndefined(); + }); + + test('should pass for v1AddOrUpdatePolicyConnectionsResponse pattern', () => { + const schema = { + type: 'object', + example: {}, + description: 'Response for a successful association/disassociation of connections to a policy', + additionalProperties: false, + }; + expect(completedSchema(schema)).toBeUndefined(); + }); + + test('should fail for empty object without additionalProperties: false', () => { + const schema = { + type: 'object', + }; + expect(completedSchema(schema)).toEqual([ + { message: 'properties missing for object schema' }, + ]); + }); + + test('should fail for empty object with additionalProperties: true', () => { + const schema = { + type: 'object', + additionalProperties: true, + }; + expect(completedSchema(schema)).toEqual([ + { message: 'properties missing for object schema' }, + ]); + }); + + test('should fail for empty object with additionalProperties as schema', () => { + const schema = { + type: 'object', + additionalProperties: { type: 'string' }, + }; + expect(completedSchema(schema)).toEqual([ + { message: 'properties missing for object schema' }, + ]); + }); + + test('should pass for object with empty properties and additionalProperties: false', () => { + const schema = { + type: 'object', + properties: {}, + additionalProperties: false, + }; + expect(completedSchema(schema)).toBeUndefined(); + }); + }); + + describe('edge cases', () => { + test('should pass for non-object input', () => { + expect(completedSchema('string')).toBeUndefined(); + expect(completedSchema(123)).toBeUndefined(); + expect(completedSchema(null)).toBeUndefined(); + }); + }); }); diff --git a/test/resources/general-schema-definition/positive.json b/test/resources/general-schema-definition/positive.json index a6d3dc9..47af7a8 100644 --- a/test/resources/general-schema-definition/positive.json +++ b/test/resources/general-schema-definition/positive.json @@ -20,6 +20,27 @@ } ], "paths": { + "/ack": { + "get": { + "description": "Acknowledge.", + "operationId": "ack", + "tags": ["Sample"], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "description": "Empty success response" + } + } + } + } + } + } + }, "/test": { "get": { "description": "Get some test data.",