From 9bd323fbb2db8df5cadf28b7e6f34989cf05a535 Mon Sep 17 00:00:00 2001 From: Jeremy Weinstein Date: Tue, 16 Dec 2025 10:17:43 -0800 Subject: [PATCH] fix: empty field checks --- .../ui/utils/test-field-empty.test.ts | 54 +++++++++++++++++++ .../root-cms/ui/utils/test-field-empty.ts | 13 ++++- 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 packages/root-cms/ui/utils/test-field-empty.test.ts diff --git a/packages/root-cms/ui/utils/test-field-empty.test.ts b/packages/root-cms/ui/utils/test-field-empty.test.ts new file mode 100644 index 000000000..6b254e2d4 --- /dev/null +++ b/packages/root-cms/ui/utils/test-field-empty.test.ts @@ -0,0 +1,54 @@ +import {describe, it, expect} from 'vitest'; +import {Field, ObjectField} from '../../core/schema.js'; +import {testFieldEmpty} from './test-field-empty.js'; + +describe('testFieldEmpty', () => { + const objectField: ObjectField = { + type: 'object', + fields: [ + {type: 'string', id: 'foo'}, + {type: 'string', id: 'bar'}, + ], + }; + + const arrayField: Field = { + type: 'array', + of: objectField, + }; + + describe('array', () => { + it('should return false for a plain non-empty array', () => { + const plainArray = [{foo: 'a'}, {foo: 'b'}]; + expect(testFieldEmpty(arrayField, plainArray)).toBe(false); + }); + + it('should return true for an empty array', () => { + const emptyArray: any[] = []; + expect(testFieldEmpty(arrayField, emptyArray)).toBe(true); + }); + + it('should return false for a normalized non-empty array', () => { + const normalizedArray = {_array: ['id1'], id1: {foo: 'a'}}; + expect(testFieldEmpty(arrayField, normalizedArray)).toBe(false); + }); + + it('should return true for a normalized array with empty items', () => { + const normalizedArray = {_array: ['id1'], id1: {foo: ''}}; + expect(testFieldEmpty(arrayField, normalizedArray)).toBe(true); + }); + }); + + describe('object', () => { + it('should return true for an empty object', () => { + expect(testFieldEmpty(objectField, {})).toBe(true); + }); + + it('should return true for an object with empty fields', () => { + expect(testFieldEmpty(objectField, {foo: '', bar: ''})).toBe(true); + }); + + it('should return false for an object with non-empty fields', () => { + expect(testFieldEmpty(objectField, {foo: 'hello'})).toBe(false); + }); + }); +}); diff --git a/packages/root-cms/ui/utils/test-field-empty.ts b/packages/root-cms/ui/utils/test-field-empty.ts index 0cd6c2ea3..3eb0f488b 100644 --- a/packages/root-cms/ui/utils/test-field-empty.ts +++ b/packages/root-cms/ui/utils/test-field-empty.ts @@ -52,6 +52,17 @@ export function testFieldEmpty( } return true; case 'array': + if (Array.isArray(value)) { + if (value.length === 0) { + return true; + } + for (const item of value) { + if (!testFieldEmpty(field.of, item, types)) { + return false; + } + } + return true; + } if ( !isObject(value) || !Array.isArray(value._array) || @@ -64,7 +75,7 @@ export function testFieldEmpty( return false; } } - return false; + return true; case 'oneof': { if (!isObject(value) || !value._type) { return true;