diff --git a/packages/vest/src/exports/SuiteSerializer.ts b/packages/vest/src/exports/SuiteSerializer.ts index a771315f7..34e8aacbf 100644 --- a/packages/vest/src/exports/SuiteSerializer.ts +++ b/packages/vest/src/exports/SuiteSerializer.ts @@ -46,4 +46,8 @@ const focusMiniMap: Record = { matchAll: 'mA', }; -const MiniMap = assign({}, testMiniMap, focusMiniMap); +const MiniMap = { + keys: { + data: assign({}, testMiniMap, focusMiniMap), + }, +}; diff --git a/packages/vestjs-runtime/src/Isolate/IsolateKeys.ts b/packages/vestjs-runtime/src/Isolate/IsolateKeys.ts index 40269c930..3d01a70c7 100644 --- a/packages/vestjs-runtime/src/Isolate/IsolateKeys.ts +++ b/packages/vestjs-runtime/src/Isolate/IsolateKeys.ts @@ -43,7 +43,7 @@ export const KeyToMinified = { // } export const MinifiedToKey = invertKeyMap(KeyToMinified); -export function invertKeyMap(miniMap: Record) { +export function invertKeyMap(miniMap: Record = {}) { return Object.entries(miniMap).reduce( (acc, [key, minified]) => assign(acc, { diff --git a/packages/vestjs-runtime/src/exports/IsolateSerializer.ts b/packages/vestjs-runtime/src/exports/IsolateSerializer.ts index 759adcb27..611ab7676 100644 --- a/packages/vestjs-runtime/src/exports/IsolateSerializer.ts +++ b/packages/vestjs-runtime/src/exports/IsolateSerializer.ts @@ -26,7 +26,7 @@ export class IsolateSerializer { // eslint-disable-next-line max-statements, complexity static deserialize( node: Record | TIsolate | string, - payloadMiniMap: Maybe + miniMaps: Maybe ): TIsolate { // the assumption is that the tree is built correctly, // but the children are missing the parent property to @@ -35,7 +35,7 @@ export class IsolateSerializer { // to avoid circular references during serialization. // we need to rebuild the tree and add back the parent property to the children // and the keys property to the parents. - const inverseMinimap = invertKeyMap(payloadMiniMap ?? {}); + const inverseMinimap = invertKeyMap(miniMaps?.keys?.data); // Validate the root object const root = isStringValue(node) @@ -107,13 +107,13 @@ export class IsolateSerializer { static serialize( isolate: Nullable, - miniMap: Maybe + miniMaps: Maybe ): string { if (isNullish(isolate)) { return ''; } - return JSON.stringify(transformIsolate(isolate, miniMap)); + return JSON.stringify(transformIsolate(isolate, miniMaps)); } static expandChildren(node: Record): Nullable { @@ -134,18 +134,18 @@ export class IsolateSerializer { // eslint-disable-next-line max-statements, complexity function transformIsolate( isolate: TIsolate, - miniMap: Maybe + miniMaps: Maybe ): Record { const next: Record = {}; if (isolate.children) { next[MinifiedKeys.Children] = isolate.children.map(isolate => - transformIsolate(isolate, miniMap) + transformIsolate(isolate, miniMaps) ); } if (!isEmpty(isolate.data)) { - next[MinifiedKeys.Data] = transformKeys(isolate.data, miniMap); + next[MinifiedKeys.Data] = transformKeys(isolate.data, miniMaps?.keys?.data); } for (const key in isolate) { @@ -163,7 +163,7 @@ function transformIsolate( } const keyToUse = minifyKey(key); - next[keyToUse] = value; + next[keyToUse] = minifyValueByKey(key, value, miniMaps); } return next; @@ -177,6 +177,20 @@ function minifyKey(key: string): string { return KeyToMinified[key as keyof typeof KeyToMinified] ?? key; } +function minifyValueByKey( + key: string, + value: any, + miniMaps: Maybe +): any { + if (isNullish(value)) { + return value; + } + + const keyMap = miniMaps?.values?.[key as keyof MiniMaps['values']]; + + return keyMap ? keyMap[value] ?? value : value; +} + function transformKeys( data: Record, keyMap: Maybe @@ -199,3 +213,13 @@ function transformKeys( } type MiniMap = Record; + +type MiniMaps = Partial<{ + keys: Partial<{ + [IsolateKeys.Data]: MiniMap; + }>; + values: Partial<{ + [IsolateKeys.Status]: MiniMap; + [IsolateKeys.Type]: MiniMap; + }>; +}>; diff --git a/packages/vestjs-runtime/src/exports/__tests__/IsolateSerializer.test.ts b/packages/vestjs-runtime/src/exports/__tests__/IsolateSerializer.test.ts index 1d03971f7..5c81fe60c 100644 --- a/packages/vestjs-runtime/src/exports/__tests__/IsolateSerializer.test.ts +++ b/packages/vestjs-runtime/src/exports/__tests__/IsolateSerializer.test.ts @@ -3,12 +3,12 @@ import { Maybe } from 'vest-utils'; import { Isolate, TIsolate } from 'Isolate'; import { MinifiedKeys } from 'IsolateKeys'; import { IsolateSerializer } from 'IsolateSerializer'; -import { VestRuntime } from 'vestjs-runtime'; +import { IsolateMutator, VestRuntime } from 'vestjs-runtime'; describe('IsolateSerializer', () => { describe('serialize', () => { it('Should produce serialized dump', () => { - const { serialized } = createSerialized(); + const { serialized } = createRoot(); expect(serialized).toMatchSnapshot(); }); @@ -16,7 +16,7 @@ describe('IsolateSerializer', () => { describe('deserialize', () => { it('Should fully inflate the tree', () => { - const { root, serialized } = createSerialized(); + const { root, serialized } = createRoot(); const inflated = IsolateSerializer.deserialize(serialized); @@ -48,7 +48,7 @@ describe('IsolateSerializer', () => { }); test('When data is empty, should not add data property', () => { - const { serialized } = createSerialized(); + const { serialized } = createRoot(); const inflated = IsolateSerializer.deserialize(serialized); expect(inflated?.children?.[0]).toHaveProperty('data'); @@ -59,8 +59,12 @@ describe('IsolateSerializer', () => { describe('Custom Data Serialization', () => { it('Should serialize data with custom keys', () => { - const { serialized } = createSerialized({ - some_data: 'sd', + const { serialized } = createRoot({ + keys: { + data: { + some_data: 'sd', + }, + }, }); const parsed = JSON.parse(serialized); @@ -70,19 +74,67 @@ describe('IsolateSerializer', () => { ); }); + describe('value serialization', () => { + it('Should serialize values with shorthand values', () => { + const { root } = createRoot(); + + root.status = 'pending'; + // @ts-ignore + root.children[0].status = 'done'; + // @ts-ignore + root.children[1].status = 'failed'; + + const serialized = IsolateSerializer.serialize(root, { + values: { + status: { + pending: 'p', + done: 'd', + failed: 'f', + }, + $type: { + URoot: 'UR', + UChild_1: 'UC1', + UChild_2: 'UC2', + UChild_3: 'UC3', + }, + }, + }); + + const parsed = JSON.parse(serialized); + expect(parsed[MinifiedKeys.Status]).toBe('p'); + expect(parsed.C[0][MinifiedKeys.Status]).toBe('d'); + expect(parsed.C[1][MinifiedKeys.Status]).toBe('f'); + expect(parsed[MinifiedKeys.Type]).toBe('UR'); + expect(parsed.C[0][MinifiedKeys.Type]).toBe('UC1'); + expect(parsed.C[1][MinifiedKeys.Type]).toBe('UC2'); + expect(parsed.C[2][MinifiedKeys.Type]).toBe('UC3'); + expect(serialized).toMatchInlineSnapshot( + `"{"C":[{"D":{"some_data":true},"$":"UC1","S":"d"},{"$":"UC2","S":"f"},{"$":"UC3"}],"D":{"some_data":true},"$":"UR","S":"p"}"` + ); + }); + }); + it('Should inflate with correct keys', () => { - const { serialized } = createSerialized({ - some_data: 'sd', + const { serialized } = createRoot({ + keys: { + data: { + some_data: 'sd', + }, + }, }); const inflated = IsolateSerializer.deserialize(serialized, { - some_data: 'sd', + keys: { + data: { + some_data: 'sd', + }, + }, }); expect(inflated.data.some_data).toBe(true); expect(inflated).not.toHaveProperty('sd'); expect(inflated).toEqual( - IsolateSerializer.deserialize(createSerialized().serialized) + IsolateSerializer.deserialize(createRoot().serialized) ); expect(inflated).toMatchInlineSnapshot(` { @@ -119,7 +171,7 @@ function withRunTime(fn: CB) { }); } -function createSerialized(miniMap: Maybe>) { +function createRoot(miniMap: Maybe>) { let serialized: string, root: TIsolate; withRunTime(() => {