From e9fd6ac3cccd3a67ecf2633c1506898e39c4df4c Mon Sep 17 00:00:00 2001 From: Dan Dando Date: Thu, 21 Aug 2025 14:50:56 +0100 Subject: [PATCH 1/2] fix: fixed keychain string creation for keychains with zeros --- module/src/form/utils/keyChain.spec.ts | 6 ++++++ module/src/form/utils/keyChain.ts | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/module/src/form/utils/keyChain.spec.ts b/module/src/form/utils/keyChain.spec.ts index b575b2a8..54f844dc 100644 --- a/module/src/form/utils/keyChain.spec.ts +++ b/module/src/form/utils/keyChain.spec.ts @@ -212,6 +212,12 @@ describe('keyStringFromKeyChain', () => { expect(result).toBe('test.value.3.target'); }); + it('converts a keychain to dot notation to target an item stored by keychain string when the keychain containes a zero', () => { + const keyChain = ['test', 'value', 0, 'target']; + const result = keyStringFromKeyChain(keyChain, 'dots'); + expect(result).toBe('test.value.0.target'); + }); + it('converts a keychain to bracket notation to target an item stored by keychain string', () => { const keyChain = ['test', 'value', 3, 'target']; const result = keyStringFromKeyChain(keyChain, 'brackets'); diff --git a/module/src/form/utils/keyChain.ts b/module/src/form/utils/keyChain.ts index 6f82ee49..4ad055d2 100644 --- a/module/src/form/utils/keyChain.ts +++ b/module/src/form/utils/keyChain.ts @@ -118,7 +118,7 @@ export function isArrayValue(value: unknown, attemptedAction: string): value is export function keyStringFromKeyChain(keyChain: KeyChain | undefined, mode: 'dots' | 'brackets'): string { switch (mode) { case 'dots': - return keyChain?.filter(key => !!key).join('.') ?? ''; + return keyChain?.filter(key => key !== undefined && key !== null).join('.') ?? ''; case 'brackets': return ( keyChain?.reduce((attrString, key) => { From 0134a3dd14fe470754475ec82ed01f80a76eb91c Mon Sep 17 00:00:00 2001 From: Dan Dando Date: Thu, 21 Aug 2025 20:23:35 +0100 Subject: [PATCH 2/2] fix: handles empty string case when creating string keys from keychains --- module/src/form/utils/keyChain.spec.ts | 33 ++++++++++++++++++++++++++ module/src/form/utils/keyChain.ts | 11 ++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/module/src/form/utils/keyChain.spec.ts b/module/src/form/utils/keyChain.spec.ts index 54f844dc..4fc5df76 100644 --- a/module/src/form/utils/keyChain.spec.ts +++ b/module/src/form/utils/keyChain.spec.ts @@ -2,6 +2,7 @@ import { childKeyChainStringFromParent, isArrayValue, isMyKeyChainItem, + isValidPropertyKey, keyStringFromKeyChain, mergeDeepFromKeyChain, valueByKeyChain, @@ -204,6 +205,38 @@ describe('isArrayValue', () => { }); }); +describe('isValidPropertyKey', () => { + it('returns true for a valid string key', () => { + const key = 'validKey'; + const result = isValidPropertyKey(key); + expect(result).toBeTruthy(); + }); + + it('returns true for a valid number key', () => { + const key = 123; + const result = isValidPropertyKey(key); + expect(result).toBeTruthy(); + }); + + it('returns true for 0 as a valid number key', () => { + const key = 0; + const result = isValidPropertyKey(key); + expect(result).toBeTruthy(); + }); + + it('returns false for an empty string key', () => { + const key = ''; + const result = isValidPropertyKey(key); + expect(result).toBeFalsy(); + }); + + it('returns false for undefined key', () => { + const key = undefined; + const result = isValidPropertyKey(key); + expect(result).toBeFalsy(); + }); +}); + /* validationKeyStringFromKeyChain */ describe('keyStringFromKeyChain', () => { it('converts a keychain to dot notation to target an item stored by keychain string', () => { diff --git a/module/src/form/utils/keyChain.ts b/module/src/form/utils/keyChain.ts index 4ad055d2..77a56a1b 100644 --- a/module/src/form/utils/keyChain.ts +++ b/module/src/form/utils/keyChain.ts @@ -109,6 +109,15 @@ export function isArrayValue(value: unknown, attemptedAction: string): value is return true; } +/** + * Checks a possible keyChain to make sure it is a valid keyChain. + * @param keyChain The keyChain to check. + * @returns true if the keyChain is valid, false if not. + */ +export function isValidPropertyKey(propertyKey: PropertyKey | undefined): propertyKey is PropertyKey { + return typeof propertyKey === 'number' || (typeof propertyKey === 'string' && propertyKey.length > 0); +} + /** * Converts a keyChain into a key string * @param keyChain The chain of keys passed to `formProp` and used to access the property within a nested form object. @@ -118,7 +127,7 @@ export function isArrayValue(value: unknown, attemptedAction: string): value is export function keyStringFromKeyChain(keyChain: KeyChain | undefined, mode: 'dots' | 'brackets'): string { switch (mode) { case 'dots': - return keyChain?.filter(key => key !== undefined && key !== null).join('.') ?? ''; + return keyChain?.filter(isValidPropertyKey).join('.') ?? ''; case 'brackets': return ( keyChain?.reduce((attrString, key) => {