diff --git a/packages/vest/src/core/Runtime.ts b/packages/vest/src/core/Runtime.ts index caadb302d..4d389cbaf 100644 --- a/packages/vest/src/core/Runtime.ts +++ b/packages/vest/src/core/Runtime.ts @@ -118,6 +118,6 @@ export function useResetSuite() { } export function useLoadSuite(rootNode: TIsolateSuite): void { - VestRuntime.useLoadRootNode(rootNode); + VestRuntime.useSetHistoryRoot(rootNode); useExpireSuiteResultCache(); } diff --git a/packages/vest/src/core/test/test.memo.ts b/packages/vest/src/core/test/test.memo.ts index 2df21ef30..a6808f00a 100644 --- a/packages/vest/src/core/test/test.memo.ts +++ b/packages/vest/src/core/test/test.memo.ts @@ -66,7 +66,11 @@ function useGetTestFromCache( return cache(dependencies, cacheAction); } - VestRuntime.addNodeToHistory(cachedValue); + // FIXME(@ealush 2024-08-12): This is some kind of a hack. Instead organically letting Vest set the next + // child of the isolate, we're forcing it from the outside. + // Instead, an ideal solution would probably be to have test.memo be its own isolate + // that just injects a historic output from a previous test run. + VestRuntime.useSetNextIsolateChild(cachedValue); return cachedValue; } diff --git a/packages/vest/src/hooks/__tests__/mode.test.ts b/packages/vest/src/hooks/__tests__/mode.test.ts index e36d3a053..ea680b379 100644 --- a/packages/vest/src/hooks/__tests__/mode.test.ts +++ b/packages/vest/src/hooks/__tests__/mode.test.ts @@ -184,12 +184,12 @@ describe('mode', () => { it('Should follow the same behavior as if it was not nested', () => { const suite = create(() => { group('group_1', () => { - dummyTest.failing('field_1', 'first-of-field_1'); - dummyTest.failing('field_1', 'second-of-field_1'); - dummyTest.failing('field_2', 'first-of-field_2'); - dummyTest.failing('field_2', 'second-of-field_2'); - dummyTest.failing('field_3', 'first-of-field_3'); - dummyTest.failing('field_3', 'second-of-field_3'); + Vest.test('field_1', 'first-of-field_1', () => false); + Vest.test('field_1', 'second-of-field_1', () => false); + Vest.test('field_2', 'first-of-field_2', () => false); + Vest.test('field_2', 'second-of-field_2', () => false); + Vest.test('field_3', 'first-of-field_3', () => false); + Vest.test('field_3', 'second-of-field_3', () => false); }); }); expect(suite.get().testCount).toBe(0); // sanity diff --git a/packages/vestjs-runtime/src/Isolate/Isolate.ts b/packages/vestjs-runtime/src/Isolate/Isolate.ts index 2ec4874d8..245d182f3 100644 --- a/packages/vestjs-runtime/src/Isolate/Isolate.ts +++ b/packages/vestjs-runtime/src/Isolate/Isolate.ts @@ -29,6 +29,7 @@ type UsedFeaturesOnly

= Pick< >; export class Isolate { + // eslint-disable-next-line max-statements static create( type: string, callback: CB, @@ -48,7 +49,11 @@ export class Isolate { const shouldRunNew = Object.is(nextIsolateChild, newCreatedNode); - VestRuntime.addNodeToHistory(nextIsolateChild); + if (parent) { + // We are within an isolate context. This means that + // we need to set the new node to be the child of this parent node. + VestRuntime.useSetNextIsolateChild(nextIsolateChild); + } const output = shouldRunNew ? useRunAsNew(localHistoryNode, newCreatedNode, callback) @@ -56,6 +61,13 @@ export class Isolate { IsolateMutator.saveOutput(nextIsolateChild, output); + if (!parent) { + // We're exiting the node, and there is no parent. This means + // that we're at the top level and this node should be set + // as the new root of the history tree. + VestRuntime.useSetHistoryRoot(nextIsolateChild); + } + return nextIsolateChild as TIsolate; } diff --git a/packages/vestjs-runtime/src/Isolate/__tests__/reconciliation.test.ts b/packages/vestjs-runtime/src/Isolate/__tests__/reconciliation.test.ts new file mode 100644 index 000000000..0c1adc8fc --- /dev/null +++ b/packages/vestjs-runtime/src/Isolate/__tests__/reconciliation.test.ts @@ -0,0 +1,48 @@ +import { CB } from 'vest-utils'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; + +import { TIsolate, Isolate } from 'Isolate'; +import { StateRefType, useAvailableRoot } from 'VestRuntime'; +import { IRecociler, IsolateMutator, VestRuntime } from 'vestjs-runtime'; + +describe('Reconciliation', () => { + let stateRef: StateRefType; + + beforeEach(() => { + stateRef = VestRuntime.createRef(testReconciler, () => null); + }); + + it('Should return the current node if there is no history node', () => { + let rootIsolate; + const output = VestRuntime.Run(stateRef, () => { + rootIsolate = Isolate.create(IsolateType.RunOne, () => {}); + }); + + const [historyRoot] = stateRef.historyRoot(); + + expect(historyRoot).toBe(rootIsolate); + }); + + it("should return the result of the reconciler's function when runs the second time", () => { + const isolate1 = VestRuntime.Run(stateRef, () => { + return Isolate.create(IsolateType.RunOne, () => ({ foo: 'bar' })); + }); + const isolate2 = VestRuntime.Run(stateRef, () => { + return Isolate.create(IsolateType.RunTwo, () => ({ foo: 'baz' })); + }); + + const [historyRoot] = stateRef.historyRoot(); + + expect(historyRoot).toBe(isolate2); + }); +}); + +enum IsolateType { + RunOne = 'RunOne', + RunTwo = 'RunTwo', +} + +const testReconciler: IRecociler = ( + currentNode: TIsolate, + historyNode: TIsolate, +): TIsolate => currentNode; diff --git a/packages/vestjs-runtime/src/VestRuntime.ts b/packages/vestjs-runtime/src/VestRuntime.ts index 402816a46..bab120672 100644 --- a/packages/vestjs-runtime/src/VestRuntime.ts +++ b/packages/vestjs-runtime/src/VestRuntime.ts @@ -59,14 +59,14 @@ export const Run = PersistedContext.run; export const RuntimeApi = { Run, - addNodeToHistory, createRef, persist, reset, useAvailableRoot, useCurrentCursor, useHistoryRoot, - useLoadRootNode, + useSetHistoryRoot, + useSetNextIsolateChild, useXAppData, }; @@ -131,18 +131,7 @@ export function useHistoryIsolateAtCurrentPosition() { return historyNode; } -export function addNodeToHistory(node: TIsolate): void { - const parent = useIsolate(); - if (parent) { - useSetNextIsolateChild(node); - } else { - useSetHistory(node); - } - - IsolateMutator.setParent(node, parent); -} - -export function useSetHistory(history: TIsolate) { +export function useSetHistoryRoot(history: TIsolate) { const [, setHistoryRoot] = useHistoryRoot(); setHistoryRoot(history); } @@ -172,6 +161,7 @@ export function useSetNextIsolateChild(child: TIsolate): void { invariant(currentIsolate, ErrorStrings.NO_ACTIVE_ISOLATE); IsolateMutator.addChild(currentIsolate, child); + IsolateMutator.setParent(child, currentIsolate); } export function useSetIsolateKey(key: Nullable, node: TIsolate): void { if (!key) { @@ -207,7 +197,3 @@ export function reset() { resetHistoryRoot(); } - -export function useLoadRootNode(root: TIsolate): void { - useSetHistory(root); -}