From 4e9cd86cf034e9570e6a2779463b6093f4118133 Mon Sep 17 00:00:00 2001 From: KUNDAN1334 Date: Tue, 28 Apr 2026 00:37:39 +0530 Subject: [PATCH 1/8] add test cases for recursion detection in jsonFieldToSchema --- library/src/helpers/__tests__/schema.test.ts | 82 ++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/library/src/helpers/__tests__/schema.test.ts b/library/src/helpers/__tests__/schema.test.ts index 637674997..aea0f3851 100644 --- a/library/src/helpers/__tests__/schema.test.ts +++ b/library/src/helpers/__tests__/schema.test.ts @@ -671,6 +671,88 @@ describe('SchemaHelpers', () => { }); expect(SchemaHelpers.jsonToSchema(undefined)).toEqual(schema); }); + describe('recursion detection in jsonFieldToSchema', () => { + test('should throw on a direct circular reference (object references itself)', () => { + const circular: any = { key: 'value' }; + circular.self = circular; + + expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow( + 'too much recursion. Please check document for recursion.', + ); + }); + + test('should throw on a circular reference through an array', () => { + const circularArray: any[] = ['a', 'b']; + circularArray.push(circularArray); + + expect(() => SchemaHelpers.jsonToSchema(circularArray)).toThrow( + 'too much recursion. Please check document for recursion.', + ); + }); + + test('should throw on an indirect circular reference (A references B which references A)', () => { + const a: any = { name: 'a' }; + const b: any = { name: 'b', ref: a }; + a.ref = b; + + expect(() => SchemaHelpers.jsonToSchema(a)).toThrow( + 'too much recursion. Please check document for recursion.', + ); + }); + + test('should NOT throw when the same object is referenced in two sibling branches', () => { + const shared = { type: 'string', minLength: 1 }; + const value = { + branch1: { c1: shared }, + branch2: { c2: shared }, + }; + + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); + }); + + test('should NOT throw when the same object appears in multiple array positions', () => { + const shared = { label: 'reused' }; + const value = [shared, shared, shared]; + + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); + }); + + test('should handle deep nesting without circularity', () => { + const deep = { + level1: { + level2: { + level3: { + level4: { + value: 'leaf', + }, + }, + }, + }, + }; + + expect(() => SchemaHelpers.jsonToSchema(deep)).not.toThrow(); + + const result = SchemaHelpers.jsonToSchema(deep); + expect(result.json().type).toBe('object'); + }); + + test('should handle an object containing null values without throwing', () => { + const value = { a: null, b: 'hello' }; + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); + }); + + test('should handle an object containing undefined values without throwing', () => { + const value = { a: undefined, b: 42 }; + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); + }); + + test('should remain usable after a recursion error is thrown', () => { + const circular: any = {}; + circular.self = circular; + expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow(); + expect(() => SchemaHelpers.jsonToSchema({ ok: true })).not.toThrow(); + }); + }); }); describe('.getCustomExtensions', () => { From 74effa065c98c3208fb140de448f396e86c715b3 Mon Sep 17 00:00:00 2001 From: KUNDAN1334 Date: Tue, 5 May 2026 23:19:03 +0530 Subject: [PATCH 2/8] Update schema.test.ts --- library/src/helpers/__tests__/schema.test.ts | 44 ++++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/library/src/helpers/__tests__/schema.test.ts b/library/src/helpers/__tests__/schema.test.ts index fb1104cdf..b43209fec 100644 --- a/library/src/helpers/__tests__/schema.test.ts +++ b/library/src/helpers/__tests__/schema.test.ts @@ -673,50 +673,55 @@ describe('SchemaHelpers', () => { }); describe('recursion detection in jsonFieldToSchema', () => { test('should throw on a direct circular reference (object references itself)', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any const circular: any = { key: 'value' }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access circular.self = circular; - + expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow( 'too much recursion. Please check document for recursion.', ); }); - + test('should throw on a circular reference through an array', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any const circularArray: any[] = ['a', 'b']; - circularArray.push(circularArray); - + circularArray.push(circularArray); + expect(() => SchemaHelpers.jsonToSchema(circularArray)).toThrow( 'too much recursion. Please check document for recursion.', ); }); - + test('should throw on an indirect circular reference (A references B which references A)', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any const a: any = { name: 'a' }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any const b: any = { name: 'b', ref: a }; - a.ref = b; - + a.ref = b; + expect(() => SchemaHelpers.jsonToSchema(a)).toThrow( 'too much recursion. Please check document for recursion.', ); }); - + test('should NOT throw when the same object is referenced in two sibling branches', () => { const shared = { type: 'string', minLength: 1 }; const value = { branch1: { c1: shared }, branch2: { c2: shared }, }; - + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); }); - + test('should NOT throw when the same object appears in multiple array positions', () => { const shared = { label: 'reused' }; const value = [shared, shared, shared]; - + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); }); - + test('should handle deep nesting without circularity', () => { const deep = { level1: { @@ -729,31 +734,34 @@ describe('SchemaHelpers', () => { }, }, }; - + expect(() => SchemaHelpers.jsonToSchema(deep)).not.toThrow(); - + const result = SchemaHelpers.jsonToSchema(deep); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call expect(result.json().type).toBe('object'); }); - + test('should handle an object containing null values without throwing', () => { const value = { a: null, b: 'hello' }; expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); }); - + test('should handle an object containing undefined values without throwing', () => { const value = { a: undefined, b: 42 }; expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); }); - + test('should remain usable after a recursion error is thrown', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any const circular: any = {}; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access circular.self = circular; + expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow(); expect(() => SchemaHelpers.jsonToSchema({ ok: true })).not.toThrow(); }); }); - }); describe('.getCustomExtensions', () => { test('should return extensions', () => { From f4eb025538de3702b7c156613855b57969705b28 Mon Sep 17 00:00:00 2001 From: KUNDAN1334 Date: Tue, 5 May 2026 23:25:27 +0530 Subject: [PATCH 3/8] Update schema.test.ts --- library/src/helpers/__tests__/schema.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/library/src/helpers/__tests__/schema.test.ts b/library/src/helpers/__tests__/schema.test.ts index b43209fec..b1b17ef0d 100644 --- a/library/src/helpers/__tests__/schema.test.ts +++ b/library/src/helpers/__tests__/schema.test.ts @@ -959,6 +959,7 @@ describe('SchemaHelpers', () => { expect(result).toEqual(expected); }); }); +}); describe('.applicatorSchemaName', () => { const FIRST_CASE = 'first case'; From 4db6aeaff28677ead194ec8b3371b485b0c53121 Mon Sep 17 00:00:00 2001 From: KUNDAN1334 Date: Tue, 5 May 2026 23:30:26 +0530 Subject: [PATCH 4/8] Update schema.test.ts --- library/src/helpers/__tests__/schema.test.ts | 378 +++++++++---------- 1 file changed, 189 insertions(+), 189 deletions(-) diff --git a/library/src/helpers/__tests__/schema.test.ts b/library/src/helpers/__tests__/schema.test.ts index b1b17ef0d..3d17467bc 100644 --- a/library/src/helpers/__tests__/schema.test.ts +++ b/library/src/helpers/__tests__/schema.test.ts @@ -677,51 +677,51 @@ describe('SchemaHelpers', () => { const circular: any = { key: 'value' }; // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access circular.self = circular; - + expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow( 'too much recursion. Please check document for recursion.', ); }); - + test('should throw on a circular reference through an array', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const circularArray: any[] = ['a', 'b']; circularArray.push(circularArray); - + expect(() => SchemaHelpers.jsonToSchema(circularArray)).toThrow( 'too much recursion. Please check document for recursion.', ); }); - + test('should throw on an indirect circular reference (A references B which references A)', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const a: any = { name: 'a' }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const b: any = { name: 'b', ref: a }; a.ref = b; - + expect(() => SchemaHelpers.jsonToSchema(a)).toThrow( 'too much recursion. Please check document for recursion.', ); }); - + test('should NOT throw when the same object is referenced in two sibling branches', () => { const shared = { type: 'string', minLength: 1 }; const value = { branch1: { c1: shared }, branch2: { c2: shared }, }; - + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); }); - + test('should NOT throw when the same object appears in multiple array positions', () => { const shared = { label: 'reused' }; const value = [shared, shared, shared]; - + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); }); - + test('should handle deep nesting without circularity', () => { const deep = { level1: { @@ -734,232 +734,232 @@ describe('SchemaHelpers', () => { }, }, }; - + expect(() => SchemaHelpers.jsonToSchema(deep)).not.toThrow(); - + const result = SchemaHelpers.jsonToSchema(deep); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call expect(result.json().type).toBe('object'); }); - + test('should handle an object containing null values without throwing', () => { const value = { a: null, b: 'hello' }; expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); }); - + test('should handle an object containing undefined values without throwing', () => { const value = { a: undefined, b: 42 }; expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); }); - + test('should remain usable after a recursion error is thrown', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const circular: any = {}; // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access circular.self = circular; - + expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow(); expect(() => SchemaHelpers.jsonToSchema({ ok: true })).not.toThrow(); }); }); - describe('.getCustomExtensions', () => { - test('should return extensions', () => { - const schema = new Schema({ - type: 'string', - minLength: 1, - 'x-foo': true, - 'x-bar': false, - }); - const result = SchemaHelpers.getCustomExtensions(schema); - expect(result).toEqual({ 'x-foo': true, 'x-bar': false }); - }); - - test('should skip private extensions', () => { - const schema = new Schema({ - type: 'object', - additionalProperties: false, - 'x-foo': true, - 'x-bar': false, - 'x-parser-foo': true, - 'x-schema-private-bar': false, - }); - const result = SchemaHelpers.getCustomExtensions(schema); - expect(result).toEqual({ 'x-foo': true, 'x-bar': false }); - }); - }); - - describe('.getDependentRequired', () => { - test('should return undefined when dependencies is not defined', () => { - const schema = new Schema({ - properties: { - foo: { type: 'string' }, - bar: { type: 'string' }, - zor: { type: 'string' }, - }, - }); - - const fooResult = SchemaHelpers.getDependentRequired('foo', schema); - expect(fooResult).toEqual(undefined); - const barResult = SchemaHelpers.getDependentRequired('bar', schema); - expect(barResult).toEqual(undefined); - const zorResult = SchemaHelpers.getDependentRequired('zor', schema); - expect(zorResult).toEqual(undefined); - }); - - test('should return dependent required (simple case)', () => { - const schema = new Schema({ - properties: { - foo: { type: 'string' }, - bar: { type: 'string' }, - zor: { type: 'string' }, - }, - dependencies: { - foo: ['bar'], - }, - }); - - const fooResult = SchemaHelpers.getDependentRequired('foo', schema); - expect(fooResult).toEqual(undefined); - const barResult = SchemaHelpers.getDependentRequired('bar', schema); - expect(barResult).toEqual(['foo']); - const zorResult = SchemaHelpers.getDependentRequired('zor', schema); - expect(zorResult).toEqual(undefined); - }); + describe('.getCustomExtensions', () => { + test('should return extensions', () => { + const schema = new Schema({ + type: 'string', + minLength: 1, + 'x-foo': true, + 'x-bar': false, + }); + const result = SchemaHelpers.getCustomExtensions(schema); + expect(result).toEqual({ 'x-foo': true, 'x-bar': false }); + }); + + test('should skip private extensions', () => { + const schema = new Schema({ + type: 'object', + additionalProperties: false, + 'x-foo': true, + 'x-bar': false, + 'x-parser-foo': true, + 'x-schema-private-bar': false, + }); + const result = SchemaHelpers.getCustomExtensions(schema); + expect(result).toEqual({ 'x-foo': true, 'x-bar': false }); + }); + }); + + describe('.getDependentRequired', () => { + test('should return undefined when dependencies is not defined', () => { + const schema = new Schema({ + properties: { + foo: { type: 'string' }, + bar: { type: 'string' }, + zor: { type: 'string' }, + }, + }); + + const fooResult = SchemaHelpers.getDependentRequired('foo', schema); + expect(fooResult).toEqual(undefined); + const barResult = SchemaHelpers.getDependentRequired('bar', schema); + expect(barResult).toEqual(undefined); + const zorResult = SchemaHelpers.getDependentRequired('zor', schema); + expect(zorResult).toEqual(undefined); + }); + + test('should return dependent required (simple case)', () => { + const schema = new Schema({ + properties: { + foo: { type: 'string' }, + bar: { type: 'string' }, + zor: { type: 'string' }, + }, + dependencies: { + foo: ['bar'], + }, + }); + + const fooResult = SchemaHelpers.getDependentRequired('foo', schema); + expect(fooResult).toEqual(undefined); + const barResult = SchemaHelpers.getDependentRequired('bar', schema); + expect(barResult).toEqual(['foo']); + const zorResult = SchemaHelpers.getDependentRequired('zor', schema); + expect(zorResult).toEqual(undefined); + }); + + test('should return dependent required (complex case)', () => { + const schema = new Schema({ + properties: { + foo: { type: 'string' }, + bar: { type: 'string' }, + zor: { type: 'string' }, + }, + dependencies: { + foo: ['bar'], + bar: ['foo', 'zor'], + zor: ['foo', 'bar'], + }, + }); - test('should return dependent required (complex case)', () => { - const schema = new Schema({ - properties: { - foo: { type: 'string' }, - bar: { type: 'string' }, - zor: { type: 'string' }, - }, - dependencies: { - foo: ['bar'], - bar: ['foo', 'zor'], - zor: ['foo', 'bar'], - }, + const fooResult = SchemaHelpers.getDependentRequired('foo', schema); + expect(fooResult).toEqual(['bar', 'zor']); + const barResult = SchemaHelpers.getDependentRequired('bar', schema); + expect(barResult).toEqual(['foo', 'zor']); + const zorResult = SchemaHelpers.getDependentRequired('zor', schema); + expect(zorResult).toEqual(['bar']); }); - - const fooResult = SchemaHelpers.getDependentRequired('foo', schema); - expect(fooResult).toEqual(['bar', 'zor']); - const barResult = SchemaHelpers.getDependentRequired('bar', schema); - expect(barResult).toEqual(['foo', 'zor']); - const zorResult = SchemaHelpers.getDependentRequired('zor', schema); - expect(zorResult).toEqual(['bar']); }); - }); - describe('.getDependentSchemas', () => { - test('should return undefined when dependencies is not defined', () => { - const schema = new Schema({ - type: 'object', - properties: { - name: { - type: 'string', - }, - credit_card: { - type: 'string', + describe('.getDependentSchemas', () => { + test('should return undefined when dependencies is not defined', () => { + const schema = new Schema({ + type: 'object', + properties: { + name: { + type: 'string', + }, + credit_card: { + type: 'string', + }, }, - }, - required: ['name'], - }); + required: ['name'], + }); - const result = SchemaHelpers.getDependentSchemas(schema); - expect(result).toEqual(undefined); - }); + const result = SchemaHelpers.getDependentSchemas(schema); + expect(result).toEqual(undefined); + }); - test('should return dependent schemas (simple case)', () => { - const jsonSchema = { - type: 'object', - properties: { - name: { - type: 'string', - }, - credit_card: { - type: 'string', + test('should return dependent schemas (simple case)', () => { + const jsonSchema = { + type: 'object', + properties: { + name: { + type: 'string', + }, + credit_card: { + type: 'string', + }, }, - }, - required: ['name'], - dependencies: { - credit_card: { - properties: { - billing_address: { type: 'string' }, + required: ['name'], + dependencies: { + credit_card: { + properties: { + billing_address: { type: 'string' }, + }, + required: ['billing_address'], }, - required: ['billing_address'], }, - }, - }; - const schema = new Schema(jsonSchema as never); - const expected = new Schema({ - type: 'object', - properties: { - credit_card: { - properties: { - billing_address: { type: 'string' }, + }; + const schema = new Schema(jsonSchema as never); + const expected = new Schema({ + type: 'object', + properties: { + credit_card: { + properties: { + billing_address: { type: 'string' }, + }, + required: ['billing_address'], }, - required: ['billing_address'], }, - }, - 'x-schema-private-render-additional-info': false, - }); + 'x-schema-private-render-additional-info': false, + }); - const result = SchemaHelpers.getDependentSchemas(schema); - expect(result).toEqual(expected); - }); + const result = SchemaHelpers.getDependentSchemas(schema); + expect(result).toEqual(expected); + }); - test('should return dependent schemas (complex case)', () => { - const jsonSchema = { - type: 'object', - properties: { - name: { - type: 'string', - }, - credit_card: { - type: 'string', - }, - }, - required: ['name'], - dependencies: { - credit_card: { - properties: { - billing_address: { type: 'string' }, + test('should return dependent schemas (complex case)', () => { + const jsonSchema = { + type: 'object', + properties: { + name: { + type: 'string', }, - required: ['billing_address'], - }, - billing_address: { - properties: { - account: { type: 'string' }, + credit_card: { + type: 'string', }, - required: ['account'], }, - }, - }; - const schema = new Schema(jsonSchema as never); - const expected = new Schema({ - type: 'object', - properties: { - credit_card: { - properties: { - billing_address: { type: 'string' }, + required: ['name'], + dependencies: { + credit_card: { + properties: { + billing_address: { type: 'string' }, + }, + required: ['billing_address'], + }, + billing_address: { + properties: { + account: { type: 'string' }, + }, + required: ['account'], }, - required: ['billing_address'], }, - billing_address: { - properties: { - account: { type: 'string' }, + }; + const schema = new Schema(jsonSchema as never); + const expected = new Schema({ + type: 'object', + properties: { + credit_card: { + properties: { + billing_address: { type: 'string' }, + }, + required: ['billing_address'], + }, + billing_address: { + properties: { + account: { type: 'string' }, + }, + required: ['account'], }, - required: ['account'], }, - }, - 'x-schema-private-render-additional-info': false, - }); + 'x-schema-private-render-additional-info': false, + }); - const result = SchemaHelpers.getDependentSchemas(schema); - expect(result).toEqual(expected); + const result = SchemaHelpers.getDependentSchemas(schema); + expect(result).toEqual(expected); + }); }); }); -}); describe('.applicatorSchemaName', () => { const FIRST_CASE = 'first case'; From c0f58a204d92226b398813e96bc75bde287ff280 Mon Sep 17 00:00:00 2001 From: KUNDAN1334 Date: Tue, 5 May 2026 23:38:37 +0530 Subject: [PATCH 5/8] Update schema.test.ts --- library/src/helpers/__tests__/schema.test.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/library/src/helpers/__tests__/schema.test.ts b/library/src/helpers/__tests__/schema.test.ts index 3d17467bc..ca05c8249 100644 --- a/library/src/helpers/__tests__/schema.test.ts +++ b/library/src/helpers/__tests__/schema.test.ts @@ -675,9 +675,10 @@ describe('SchemaHelpers', () => { test('should throw on a direct circular reference (object references itself)', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const circular: any = { key: 'value' }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment circular.self = circular; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow( 'too much recursion. Please check document for recursion.', ); @@ -688,6 +689,7 @@ describe('SchemaHelpers', () => { const circularArray: any[] = ['a', 'b']; circularArray.push(circularArray); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return expect(() => SchemaHelpers.jsonToSchema(circularArray)).toThrow( 'too much recursion. Please check document for recursion.', ); @@ -696,10 +698,12 @@ describe('SchemaHelpers', () => { test('should throw on an indirect circular reference (A references B which references A)', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const a: any = { name: 'a' }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment const b: any = { name: 'b', ref: a }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment a.ref = b; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return expect(() => SchemaHelpers.jsonToSchema(a)).toThrow( 'too much recursion. Please check document for recursion.', ); @@ -712,6 +716,7 @@ describe('SchemaHelpers', () => { branch2: { c2: shared }, }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); }); @@ -719,6 +724,7 @@ describe('SchemaHelpers', () => { const shared = { label: 'reused' }; const value = [shared, shared, shared]; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); }); @@ -735,8 +741,10 @@ describe('SchemaHelpers', () => { }, }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return expect(() => SchemaHelpers.jsonToSchema(deep)).not.toThrow(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const result = SchemaHelpers.jsonToSchema(deep); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call expect(result.json().type).toBe('object'); @@ -744,21 +752,25 @@ describe('SchemaHelpers', () => { test('should handle an object containing null values without throwing', () => { const value = { a: null, b: 'hello' }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); }); test('should handle an object containing undefined values without throwing', () => { const value = { a: undefined, b: 42 }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); }); test('should remain usable after a recursion error is thrown', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const circular: any = {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment circular.self = circular; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return expect(() => SchemaHelpers.jsonToSchema({ ok: true })).not.toThrow(); }); }); From 7d0af316efb314f60ee76c5c4d7bbf9fa63c0248 Mon Sep 17 00:00:00 2001 From: KUNDAN1334 Date: Tue, 5 May 2026 23:47:06 +0530 Subject: [PATCH 6/8] test: add recursion detection test cases --- library/src/helpers/__tests__/schema.test.ts | 509 +++++++++---------- 1 file changed, 251 insertions(+), 258 deletions(-) diff --git a/library/src/helpers/__tests__/schema.test.ts b/library/src/helpers/__tests__/schema.test.ts index ca05c8249..ac0ed3798 100644 --- a/library/src/helpers/__tests__/schema.test.ts +++ b/library/src/helpers/__tests__/schema.test.ts @@ -219,37 +219,37 @@ describe('SchemaHelpers', () => { test('should handle number/integer inclusive range', () => { const schema = new Schema({ minimum: 2, maximum: 5 }); const result = SchemaHelpers.humanizeConstraints(schema); - expect(result).toEqual(['2 <= value <= 5']); + expect(result).toEqual(['[ 2 .. 5 ]']); }); test('should handle number/integer exclusive range', () => { const schema = new Schema({ minimum: 2, exclusiveMaximum: 5 }); const result = SchemaHelpers.humanizeConstraints(schema); - expect(result).toEqual(['2 <= value < 5']); + expect(result).toEqual(['[ 2 .. 5 )']); }); test('should handle inclusive minimum', () => { const schema = new Schema({ minimum: 2 }); const result = SchemaHelpers.humanizeConstraints(schema); - expect(result).toEqual(['2 <= value']); + expect(result).toEqual(['>= 2']); }); test('should handle inclusive maximum', () => { const schema = new Schema({ maximum: 2 }); const result = SchemaHelpers.humanizeConstraints(schema); - expect(result).toEqual(['value <= 2']); + expect(result).toEqual(['<= 2']); }); test('should handle exclusive minimum', () => { const schema = new Schema({ exclusiveMinimum: 5 }); const result = SchemaHelpers.humanizeConstraints(schema); - expect(result).toEqual(['5 < value']); + expect(result).toEqual(['> 5']); }); test('should handle exclusive maximum', () => { const schema = new Schema({ exclusiveMaximum: 5 }); const result = SchemaHelpers.humanizeConstraints(schema); - expect(result).toEqual(['value < 5']); + expect(result).toEqual(['< 5']); }); test('should handle integer multipleOf', () => { @@ -671,305 +671,298 @@ describe('SchemaHelpers', () => { }); expect(SchemaHelpers.jsonToSchema(undefined)).toEqual(schema); }); - describe('recursion detection in jsonFieldToSchema', () => { - test('should throw on a direct circular reference (object references itself)', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const circular: any = { key: 'value' }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment - circular.self = circular; - - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow( - 'too much recursion. Please check document for recursion.', - ); - }); - - test('should throw on a circular reference through an array', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const circularArray: any[] = ['a', 'b']; - circularArray.push(circularArray); - - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(circularArray)).toThrow( - 'too much recursion. Please check document for recursion.', - ); - }); + }); - test('should throw on an indirect circular reference (A references B which references A)', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const a: any = { name: 'a' }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment - const b: any = { name: 'b', ref: a }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment - a.ref = b; - - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(a)).toThrow( - 'too much recursion. Please check document for recursion.', - ); - }); + describe('recursion detection in jsonFieldToSchema', () => { + test('should throw on a direct circular reference (object references itself)', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const circular: any = { key: 'value' }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment + circular.self = circular; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow( + 'too much recursion. Please check document for recursion.', + ); + }); - test('should NOT throw when the same object is referenced in two sibling branches', () => { - const shared = { type: 'string', minLength: 1 }; - const value = { - branch1: { c1: shared }, - branch2: { c2: shared }, - }; + test('should throw on a circular reference through an array', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const circularArray: any[] = ['a', 'b']; + circularArray.push(circularArray); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(circularArray)).toThrow( + 'too much recursion. Please check document for recursion.', + ); + }); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); - }); + test('should throw on an indirect circular reference (A references B which references A)', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const a: any = { name: 'a' }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment + const b: any = { name: 'b', ref: a }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment + a.ref = b; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(a)).toThrow( + 'too much recursion. Please check document for recursion.', + ); + }); - test('should NOT throw when the same object appears in multiple array positions', () => { - const shared = { label: 'reused' }; - const value = [shared, shared, shared]; + test('should NOT throw when the same object is referenced in two sibling branches', () => { + const shared = { type: 'string', minLength: 1 }; + const value = { + branch1: { c1: shared }, + branch2: { c2: shared }, + }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); + }); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); - }); + test('should NOT throw when the same object appears in multiple array positions', () => { + const shared = { label: 'reused' }; + const value = [shared, shared, shared]; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); + }); - test('should handle deep nesting without circularity', () => { - const deep = { - level1: { - level2: { - level3: { - level4: { - value: 'leaf', - }, + test('should handle deep nesting without circularity', () => { + const deep = { + level1: { + level2: { + level3: { + level4: { + value: 'leaf', }, }, }, - }; + }, + }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(deep)).not.toThrow(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result = SchemaHelpers.jsonToSchema(deep); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + expect(result.json().type).toBe('object'); + }); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(deep)).not.toThrow(); + test('should handle an object containing null values without throwing', () => { + const value = { a: null, b: 'hello' }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); + }); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result = SchemaHelpers.jsonToSchema(deep); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - expect(result.json().type).toBe('object'); - }); + test('should handle an object containing undefined values without throwing', () => { + const value = { a: undefined, b: 42 }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); + }); - test('should handle an object containing null values without throwing', () => { - const value = { a: null, b: 'hello' }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); - }); + test('should remain usable after a recursion error is thrown', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const circular: any = {}; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment + circular.self = circular; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema({ ok: true })).not.toThrow(); + }); + }); - test('should handle an object containing undefined values without throwing', () => { - const value = { a: undefined, b: 42 }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); + describe('.getCustomExtensions', () => { + test('should return extensions', () => { + const schema = new Schema({ + type: 'string', + minLength: 1, + 'x-foo': true, + 'x-bar': false, }); + const result = SchemaHelpers.getCustomExtensions(schema); + expect(result).toEqual({ 'x-foo': true, 'x-bar': false }); + }); - test('should remain usable after a recursion error is thrown', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const circular: any = {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment - circular.self = circular; - - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema({ ok: true })).not.toThrow(); + test('should skip private extensions', () => { + const schema = new Schema({ + type: 'object', + additionalProperties: false, + 'x-foo': true, + 'x-bar': false, + 'x-parser-foo': true, + 'x-schema-private-bar': false, }); + const result = SchemaHelpers.getCustomExtensions(schema); + expect(result).toEqual({ 'x-foo': true, 'x-bar': false }); }); + }); - describe('.getCustomExtensions', () => { - test('should return extensions', () => { - const schema = new Schema({ - type: 'string', - minLength: 1, - 'x-foo': true, - 'x-bar': false, - }); - const result = SchemaHelpers.getCustomExtensions(schema); - expect(result).toEqual({ 'x-foo': true, 'x-bar': false }); + describe('.getDependentRequired', () => { + test('should return undefined when dependencies is not defined', () => { + const schema = new Schema({ + properties: { + foo: { type: 'string' }, + bar: { type: 'string' }, + zor: { type: 'string' }, + }, }); - test('should skip private extensions', () => { - const schema = new Schema({ - type: 'object', - additionalProperties: false, - 'x-foo': true, - 'x-bar': false, - 'x-parser-foo': true, - 'x-schema-private-bar': false, - }); - const result = SchemaHelpers.getCustomExtensions(schema); - expect(result).toEqual({ 'x-foo': true, 'x-bar': false }); - }); + const fooResult = SchemaHelpers.getDependentRequired('foo', schema); + expect(fooResult).toEqual(undefined); + const barResult = SchemaHelpers.getDependentRequired('bar', schema); + expect(barResult).toEqual(undefined); + const zorResult = SchemaHelpers.getDependentRequired('zor', schema); + expect(zorResult).toEqual(undefined); }); - describe('.getDependentRequired', () => { - test('should return undefined when dependencies is not defined', () => { - const schema = new Schema({ - properties: { - foo: { type: 'string' }, - bar: { type: 'string' }, - zor: { type: 'string' }, - }, - }); - - const fooResult = SchemaHelpers.getDependentRequired('foo', schema); - expect(fooResult).toEqual(undefined); - const barResult = SchemaHelpers.getDependentRequired('bar', schema); - expect(barResult).toEqual(undefined); - const zorResult = SchemaHelpers.getDependentRequired('zor', schema); - expect(zorResult).toEqual(undefined); + test('should return dependent required (simple case)', () => { + const schema = new Schema({ + properties: { + foo: { type: 'string' }, + bar: { type: 'string' }, + zor: { type: 'string' }, + }, + dependencies: { + foo: ['bar'], + }, }); - test('should return dependent required (simple case)', () => { - const schema = new Schema({ - properties: { - foo: { type: 'string' }, - bar: { type: 'string' }, - zor: { type: 'string' }, - }, - dependencies: { - foo: ['bar'], - }, - }); - - const fooResult = SchemaHelpers.getDependentRequired('foo', schema); - expect(fooResult).toEqual(undefined); - const barResult = SchemaHelpers.getDependentRequired('bar', schema); - expect(barResult).toEqual(['foo']); - const zorResult = SchemaHelpers.getDependentRequired('zor', schema); - expect(zorResult).toEqual(undefined); + const fooResult = SchemaHelpers.getDependentRequired('foo', schema); + expect(fooResult).toEqual(undefined); + const barResult = SchemaHelpers.getDependentRequired('bar', schema); + expect(barResult).toEqual(['foo']); + const zorResult = SchemaHelpers.getDependentRequired('zor', schema); + expect(zorResult).toEqual(undefined); + }); + + test('should return dependent required (complex case)', () => { + const schema = new Schema({ + properties: { + foo: { type: 'string' }, + bar: { type: 'string' }, + zor: { type: 'string' }, + }, + dependencies: { + foo: ['bar'], + bar: ['foo', 'zor'], + zor: ['foo', 'bar'], + }, }); - test('should return dependent required (complex case)', () => { - const schema = new Schema({ - properties: { - foo: { type: 'string' }, - bar: { type: 'string' }, - zor: { type: 'string' }, + const fooResult = SchemaHelpers.getDependentRequired('foo', schema); + expect(fooResult).toEqual(['bar', 'zor']); + const barResult = SchemaHelpers.getDependentRequired('bar', schema); + expect(barResult).toEqual(['foo', 'zor']); + const zorResult = SchemaHelpers.getDependentRequired('zor', schema); + expect(zorResult).toEqual(['bar']); + }); + }); + + describe('.getDependentSchemas', () => { + test('should return undefined when dependencies is not defined', () => { + const schema = new Schema({ + type: 'object', + properties: { + name: { + type: 'string', }, - dependencies: { - foo: ['bar'], - bar: ['foo', 'zor'], - zor: ['foo', 'bar'], + credit_card: { + type: 'string', }, - }); - - const fooResult = SchemaHelpers.getDependentRequired('foo', schema); - expect(fooResult).toEqual(['bar', 'zor']); - const barResult = SchemaHelpers.getDependentRequired('bar', schema); - expect(barResult).toEqual(['foo', 'zor']); - const zorResult = SchemaHelpers.getDependentRequired('zor', schema); - expect(zorResult).toEqual(['bar']); + }, + required: ['name'], }); + + const result = SchemaHelpers.getDependentSchemas(schema); + expect(result).toEqual(undefined); }); - describe('.getDependentSchemas', () => { - test('should return undefined when dependencies is not defined', () => { - const schema = new Schema({ - type: 'object', - properties: { - name: { - type: 'string', - }, - credit_card: { - type: 'string', - }, + test('should return dependent schemas (simple case)', () => { + const jsonSchema = { + type: 'object', + properties: { + name: { + type: 'string', }, - required: ['name'], - }); - - const result = SchemaHelpers.getDependentSchemas(schema); - expect(result).toEqual(undefined); - }); - - test('should return dependent schemas (simple case)', () => { - const jsonSchema = { - type: 'object', - properties: { - name: { - type: 'string', - }, - credit_card: { - type: 'string', - }, + credit_card: { + type: 'string', }, - required: ['name'], - dependencies: { - credit_card: { - properties: { - billing_address: { type: 'string' }, - }, - required: ['billing_address'], + }, + required: ['name'], + dependencies: { + credit_card: { + properties: { + billing_address: { type: 'string' }, }, + required: ['billing_address'], }, - }; - const schema = new Schema(jsonSchema as never); - const expected = new Schema({ - type: 'object', - properties: { - credit_card: { - properties: { - billing_address: { type: 'string' }, - }, - required: ['billing_address'], + }, + }; + const schema = new Schema(jsonSchema as never); + const expected = new Schema({ + type: 'object', + properties: { + credit_card: { + properties: { + billing_address: { type: 'string' }, }, + required: ['billing_address'], }, - 'x-schema-private-render-additional-info': false, - }); - - const result = SchemaHelpers.getDependentSchemas(schema); - expect(result).toEqual(expected); + }, + 'x-schema-private-render-additional-info': false, }); - test('should return dependent schemas (complex case)', () => { - const jsonSchema = { - type: 'object', - properties: { - name: { - type: 'string', - }, - credit_card: { - type: 'string', - }, + const result = SchemaHelpers.getDependentSchemas(schema); + expect(result).toEqual(expected); + }); + + test('should return dependent schemas (complex case)', () => { + const jsonSchema = { + type: 'object', + properties: { + name: { + type: 'string', }, - required: ['name'], - dependencies: { - credit_card: { - properties: { - billing_address: { type: 'string' }, - }, - required: ['billing_address'], + credit_card: { + type: 'string', + }, + }, + required: ['name'], + dependencies: { + credit_card: { + properties: { + billing_address: { type: 'string' }, }, - billing_address: { - properties: { - account: { type: 'string' }, - }, - required: ['account'], + required: ['billing_address'], + }, + billing_address: { + properties: { + account: { type: 'string' }, }, + required: ['account'], }, - }; - const schema = new Schema(jsonSchema as never); - const expected = new Schema({ - type: 'object', - properties: { - credit_card: { - properties: { - billing_address: { type: 'string' }, - }, - required: ['billing_address'], + }, + }; + const schema = new Schema(jsonSchema as never); + const expected = new Schema({ + type: 'object', + properties: { + credit_card: { + properties: { + billing_address: { type: 'string' }, }, - billing_address: { - properties: { - account: { type: 'string' }, - }, - required: ['account'], + required: ['billing_address'], + }, + billing_address: { + properties: { + account: { type: 'string' }, }, + required: ['account'], }, - 'x-schema-private-render-additional-info': false, - }); - - const result = SchemaHelpers.getDependentSchemas(schema); - expect(result).toEqual(expected); + }, + 'x-schema-private-render-additional-info': false, }); + + const result = SchemaHelpers.getDependentSchemas(schema); + expect(result).toEqual(expected); }); }); From 6aa6ce1a55005a8b8486958c47a711deadb0848c Mon Sep 17 00:00:00 2001 From: KUNDAN1334 Date: Tue, 5 May 2026 23:49:34 +0530 Subject: [PATCH 7/8] test: add recursion detection test cases --- library/src/helpers/__tests__/schema.test.ts | 173 +++++++++---------- 1 file changed, 86 insertions(+), 87 deletions(-) diff --git a/library/src/helpers/__tests__/schema.test.ts b/library/src/helpers/__tests__/schema.test.ts index ac0ed3798..864e82ea8 100644 --- a/library/src/helpers/__tests__/schema.test.ts +++ b/library/src/helpers/__tests__/schema.test.ts @@ -671,101 +671,100 @@ describe('SchemaHelpers', () => { }); expect(SchemaHelpers.jsonToSchema(undefined)).toEqual(schema); }); - }); - - describe('recursion detection in jsonFieldToSchema', () => { - test('should throw on a direct circular reference (object references itself)', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const circular: any = { key: 'value' }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment - circular.self = circular; - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow( - 'too much recursion. Please check document for recursion.', - ); - }); + describe('recursion detection in jsonFieldToSchema', () => { + test('should throw on a direct circular reference (object references itself)', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const circular: any = { key: 'value' }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment + circular.self = circular; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow( + 'too much recursion. Please check document for recursion.', + ); + }); - test('should throw on a circular reference through an array', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const circularArray: any[] = ['a', 'b']; - circularArray.push(circularArray); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(circularArray)).toThrow( - 'too much recursion. Please check document for recursion.', - ); - }); + test('should throw on a circular reference through an array', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const circularArray: any[] = ['a', 'b']; + circularArray.push(circularArray); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(circularArray)).toThrow( + 'too much recursion. Please check document for recursion.', + ); + }); - test('should throw on an indirect circular reference (A references B which references A)', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const a: any = { name: 'a' }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment - const b: any = { name: 'b', ref: a }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment - a.ref = b; - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(a)).toThrow( - 'too much recursion. Please check document for recursion.', - ); - }); + test('should throw on an indirect circular reference (A references B which references A)', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const a: any = { name: 'a' }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment + const b: any = { name: 'b', ref: a }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment + a.ref = b; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(a)).toThrow( + 'too much recursion. Please check document for recursion.', + ); + }); - test('should NOT throw when the same object is referenced in two sibling branches', () => { - const shared = { type: 'string', minLength: 1 }; - const value = { - branch1: { c1: shared }, - branch2: { c2: shared }, - }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); - }); + test('should NOT throw when the same object is referenced in two sibling branches', () => { + const shared = { type: 'string', minLength: 1 }; + const value = { + branch1: { c1: shared }, + branch2: { c2: shared }, + }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); + }); - test('should NOT throw when the same object appears in multiple array positions', () => { - const shared = { label: 'reused' }; - const value = [shared, shared, shared]; - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); - }); + test('should NOT throw when the same object appears in multiple array positions', () => { + const shared = { label: 'reused' }; + const value = [shared, shared, shared]; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); + }); - test('should handle deep nesting without circularity', () => { - const deep = { - level1: { - level2: { - level3: { - level4: { - value: 'leaf', + test('should handle deep nesting without circularity', () => { + const deep = { + level1: { + level2: { + level3: { + level4: { + value: 'leaf', + }, }, }, }, - }, - }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(deep)).not.toThrow(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result = SchemaHelpers.jsonToSchema(deep); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - expect(result.json().type).toBe('object'); - }); - - test('should handle an object containing null values without throwing', () => { - const value = { a: null, b: 'hello' }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); - }); - - test('should handle an object containing undefined values without throwing', () => { - const value = { a: undefined, b: 42 }; - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); - }); - - test('should remain usable after a recursion error is thrown', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const circular: any = {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment - circular.self = circular; - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - expect(() => SchemaHelpers.jsonToSchema({ ok: true })).not.toThrow(); + }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(deep)).not.toThrow(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const result = SchemaHelpers.jsonToSchema(deep); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + expect(result.json().type).toBe('object'); + }); + + test('should handle an object containing null values without throwing', () => { + const value = { a: null, b: 'hello' }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); + }); + + test('should handle an object containing undefined values without throwing', () => { + const value = { a: undefined, b: 42 }; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(value)).not.toThrow(); + }); + + test('should remain usable after a recursion error is thrown', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const circular: any = {}; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment + circular.self = circular; + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema(circular)).toThrow(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + expect(() => SchemaHelpers.jsonToSchema({ ok: true })).not.toThrow(); + }); }); }); From e2d0b517c7ac609ec8775969743253cef62b190f Mon Sep 17 00:00:00 2001 From: KUNDAN1334 Date: Tue, 5 May 2026 23:58:20 +0530 Subject: [PATCH 8/8] Update schema.test.ts --- library/src/helpers/__tests__/schema.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/src/helpers/__tests__/schema.test.ts b/library/src/helpers/__tests__/schema.test.ts index 864e82ea8..f63d8151d 100644 --- a/library/src/helpers/__tests__/schema.test.ts +++ b/library/src/helpers/__tests__/schema.test.ts @@ -219,37 +219,37 @@ describe('SchemaHelpers', () => { test('should handle number/integer inclusive range', () => { const schema = new Schema({ minimum: 2, maximum: 5 }); const result = SchemaHelpers.humanizeConstraints(schema); - expect(result).toEqual(['[ 2 .. 5 ]']); + expect(result).toEqual(['2 <= value <= 5']); }); test('should handle number/integer exclusive range', () => { const schema = new Schema({ minimum: 2, exclusiveMaximum: 5 }); const result = SchemaHelpers.humanizeConstraints(schema); - expect(result).toEqual(['[ 2 .. 5 )']); + expect(result).toEqual(['2 <= value < 5']); }); test('should handle inclusive minimum', () => { const schema = new Schema({ minimum: 2 }); const result = SchemaHelpers.humanizeConstraints(schema); - expect(result).toEqual(['>= 2']); + expect(result).toEqual(['2 <= value']); }); test('should handle inclusive maximum', () => { const schema = new Schema({ maximum: 2 }); const result = SchemaHelpers.humanizeConstraints(schema); - expect(result).toEqual(['<= 2']); + expect(result).toEqual(['value <= 2']); }); test('should handle exclusive minimum', () => { const schema = new Schema({ exclusiveMinimum: 5 }); const result = SchemaHelpers.humanizeConstraints(schema); - expect(result).toEqual(['> 5']); + expect(result).toEqual(['5 < value']); }); test('should handle exclusive maximum', () => { const schema = new Schema({ exclusiveMaximum: 5 }); const result = SchemaHelpers.humanizeConstraints(schema); - expect(result).toEqual(['< 5']); + expect(result).toEqual(['value < 5']); }); test('should handle integer multipleOf', () => {