vestjs-runtime 1.7.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/IsolateSerializer/package.json +12 -8
- package/README.md +3 -1
- package/dist/IsolateKeys-B21aPuBk.mjs +23 -0
- package/dist/IsolateKeys-B21aPuBk.mjs.map +1 -0
- package/dist/IsolateKeys-CCvALpZC.cjs +35 -0
- package/dist/IsolateKeys-CCvALpZC.cjs.map +1 -0
- package/dist/IsolateSerializer-B1hE3gmT.mjs +1004 -0
- package/dist/IsolateSerializer-B1hE3gmT.mjs.map +1 -0
- package/dist/IsolateSerializer-pbEf5gB2.cjs +1121 -0
- package/dist/IsolateSerializer-pbEf5gB2.cjs.map +1 -0
- package/dist/chunk-CLMFDpHK.mjs +18 -0
- package/dist/exports/IsolateSerializer.cjs +4 -0
- package/dist/exports/IsolateSerializer.mjs +4 -0
- package/dist/exports/test-utils.cjs +21 -0
- package/dist/exports/test-utils.cjs.map +1 -0
- package/dist/exports/test-utils.mjs +21 -0
- package/dist/exports/test-utils.mjs.map +1 -0
- package/dist/vestjs-runtime.cjs +153 -0
- package/dist/vestjs-runtime.cjs.map +1 -0
- package/dist/vestjs-runtime.mjs +117 -0
- package/dist/vestjs-runtime.mjs.map +1 -0
- package/docs/IsolateRegistry.docs.md +146 -0
- package/docs/Isolates.md +97 -0
- package/package.json +43 -88
- package/src/Bus.ts +46 -0
- package/src/Isolate/Isolate.ts +163 -0
- package/src/Isolate/IsolateFocused.ts +93 -0
- package/src/Isolate/IsolateIndexer.ts +42 -0
- package/src/Isolate/IsolateInspector.ts +93 -0
- package/src/Isolate/IsolateKeys.ts +18 -0
- package/src/Isolate/IsolateMutator.ts +165 -0
- package/src/Isolate/IsolateRegistry.ts +176 -0
- package/src/Isolate/IsolateReorderable.ts +11 -0
- package/src/Isolate/IsolateSelectors.ts +25 -0
- package/src/Isolate/IsolateStateMachine.ts +30 -0
- package/src/Isolate/IsolateStatus.ts +8 -0
- package/src/Isolate/IsolateTransient.ts +27 -0
- package/src/Isolate/IsolateTypes.ts +33 -0
- package/src/Isolate/__tests__/Isolate.test.ts +123 -0
- package/src/Isolate/__tests__/IsolateFocused.test.ts +199 -0
- package/src/Isolate/__tests__/IsolateInspector.test.ts +136 -0
- package/src/Isolate/__tests__/IsolateMutator.test.ts +164 -0
- package/src/Isolate/__tests__/IsolatePropagation.test.ts +170 -0
- package/src/Isolate/__tests__/IsolateReorderable.test.ts +111 -0
- package/src/Isolate/__tests__/IsolateSelectors.test.ts +72 -0
- package/src/Isolate/__tests__/IsolateStatus.test.ts +44 -0
- package/src/Isolate/__tests__/IsolateTransient.test.ts +58 -0
- package/src/Isolate/__tests__/__snapshots__/asyncIsolate.test.ts.snap +71 -0
- package/src/Isolate/__tests__/asyncIsolate.test.ts +85 -0
- package/src/IsolateWalker.ts +359 -0
- package/src/Orchestrator/RuntimeStates.ts +4 -0
- package/src/Reconciler.ts +178 -0
- package/src/RuntimeEvents.ts +9 -0
- package/src/VestRuntime.ts +421 -0
- package/src/__tests__/Bus.test.ts +57 -0
- package/src/__tests__/IsolateWalker.iterative.test.ts +77 -0
- package/src/__tests__/IsolateWalker.test.ts +418 -0
- package/src/__tests__/Reconciler.test.ts +193 -0
- package/src/__tests__/Reconciler.transient.test.ts +166 -0
- package/src/__tests__/VestRuntime.test.ts +212 -0
- package/src/__tests__/VestRuntimeStateMachine.test.ts +36 -0
- package/src/__tests__/vestjs-runtime.test.ts +19 -0
- package/src/errors/ErrorStrings.ts +6 -0
- package/src/exports/IsolateSerializer.ts +131 -0
- package/src/exports/__tests__/IsolateSerializer.test.ts +334 -0
- package/src/exports/__tests__/IsolateSerializer.transient.test.ts +101 -0
- package/src/exports/__tests__/__snapshots__/IsolateSerializer.test.ts.snap +5 -0
- package/src/exports/test-utils.ts +17 -0
- package/src/vestjs-runtime.ts +28 -0
- package/test-utils/package.json +12 -8
- package/types/Isolate-DChR7h5K.d.mts +58 -0
- package/types/Isolate-DChR7h5K.d.mts.map +1 -0
- package/types/Isolate-HYIh82M8.d.cts +58 -0
- package/types/Isolate-HYIh82M8.d.cts.map +1 -0
- package/types/IsolateSerializer-BCg01Px5.d.mts +13 -0
- package/types/IsolateSerializer-BCg01Px5.d.mts.map +1 -0
- package/types/IsolateSerializer-CQpP6A4m.d.cts +13 -0
- package/types/IsolateSerializer-CQpP6A4m.d.cts.map +1 -0
- package/types/exports/IsolateSerializer.d.cts +3 -0
- package/types/exports/IsolateSerializer.d.mts +3 -0
- package/types/exports/test-utils.d.cts +7 -0
- package/types/exports/test-utils.d.cts.map +1 -0
- package/types/exports/test-utils.d.mts +7 -0
- package/types/exports/test-utils.d.mts.map +1 -0
- package/types/vestjs-runtime.d.cts +372 -0
- package/types/vestjs-runtime.d.cts.map +1 -0
- package/types/vestjs-runtime.d.mts +370 -0
- package/types/vestjs-runtime.d.mts.map +1 -0
- package/types/vestjs-runtime.d.ts +351 -257
- package/vitest.config.ts +9 -17
- package/dist/cjs/IsolateSerializer.development.js +0 -135
- package/dist/cjs/IsolateSerializer.development.js.map +0 -1
- package/dist/cjs/IsolateSerializer.js +0 -6
- package/dist/cjs/IsolateSerializer.production.js +0 -2
- package/dist/cjs/IsolateSerializer.production.js.map +0 -1
- package/dist/cjs/package.json +0 -1
- package/dist/cjs/test-utils.development.js +0 -61
- package/dist/cjs/test-utils.development.js.map +0 -1
- package/dist/cjs/test-utils.js +0 -6
- package/dist/cjs/test-utils.production.js +0 -2
- package/dist/cjs/test-utils.production.js.map +0 -1
- package/dist/cjs/vestjs-runtime.development.js +0 -686
- package/dist/cjs/vestjs-runtime.development.js.map +0 -1
- package/dist/cjs/vestjs-runtime.js +0 -6
- package/dist/cjs/vestjs-runtime.production.js +0 -2
- package/dist/cjs/vestjs-runtime.production.js.map +0 -1
- package/dist/es/IsolateSerializer.development.js +0 -133
- package/dist/es/IsolateSerializer.development.js.map +0 -1
- package/dist/es/IsolateSerializer.production.js +0 -2
- package/dist/es/IsolateSerializer.production.js.map +0 -1
- package/dist/es/package.json +0 -1
- package/dist/es/test-utils.development.js +0 -59
- package/dist/es/test-utils.development.js.map +0 -1
- package/dist/es/test-utils.production.js +0 -2
- package/dist/es/test-utils.production.js.map +0 -1
- package/dist/es/vestjs-runtime.development.js +0 -675
- package/dist/es/vestjs-runtime.development.js.map +0 -1
- package/dist/es/vestjs-runtime.production.js +0 -2
- package/dist/es/vestjs-runtime.production.js.map +0 -1
- package/dist/umd/IsolateSerializer.development.js +0 -138
- package/dist/umd/IsolateSerializer.development.js.map +0 -1
- package/dist/umd/IsolateSerializer.production.js +0 -2
- package/dist/umd/IsolateSerializer.production.js.map +0 -1
- package/dist/umd/test-utils.development.js +0 -67
- package/dist/umd/test-utils.development.js.map +0 -1
- package/dist/umd/test-utils.production.js +0 -2
- package/dist/umd/test-utils.production.js.map +0 -1
- package/dist/umd/vestjs-runtime.development.js +0 -688
- package/dist/umd/vestjs-runtime.development.js.map +0 -1
- package/dist/umd/vestjs-runtime.production.js +0 -2
- package/dist/umd/vestjs-runtime.production.js.map +0 -1
- package/types/IsolateSerializer.d.ts +0 -42
- package/types/IsolateSerializer.d.ts.map +0 -1
- package/types/test-utils.d.ts +0 -37
- package/types/test-utils.d.ts.map +0 -1
- package/types/vestjs-runtime.d.ts.map +0 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Nullable } from 'vest-utils';
|
|
2
|
+
|
|
3
|
+
import { IsolateKeys } from './IsolateKeys';
|
|
4
|
+
import { IsolateStatus } from './IsolateStatus';
|
|
5
|
+
|
|
6
|
+
export type IsolateKey = Nullable<string>;
|
|
7
|
+
|
|
8
|
+
export type TIsolate<P extends IsolatePayload = IsolatePayload> = {
|
|
9
|
+
[IsolateKeys.AllowReorder]?: boolean;
|
|
10
|
+
[IsolateKeys.Transient]?: boolean;
|
|
11
|
+
[IsolateKeys.Parent]: Nullable<TIsolate>;
|
|
12
|
+
[IsolateKeys.Type]: string;
|
|
13
|
+
[IsolateKeys.Keys]: Nullable<Record<string, TIsolate>>;
|
|
14
|
+
[IsolateKeys.Data]: DataOnly<P>;
|
|
15
|
+
[IsolateKeys.Status]: IsolateStatus;
|
|
16
|
+
[IsolateKeys.AbortController]: Nullable<AbortController>;
|
|
17
|
+
children: Nullable<TIsolate[]>;
|
|
18
|
+
key: IsolateKey;
|
|
19
|
+
output: any;
|
|
20
|
+
} & UsedFeaturesOnly<P>;
|
|
21
|
+
|
|
22
|
+
type DataOnly<P extends IsolatePayload> = Omit<P, keyof IsolateFeatures>;
|
|
23
|
+
type UsedFeaturesOnly<P extends IsolatePayload> = Pick<
|
|
24
|
+
P,
|
|
25
|
+
keyof IsolateFeatures
|
|
26
|
+
>;
|
|
27
|
+
|
|
28
|
+
export type IsolatePayload<P = Record<string, any>> = P & IsolateFeatures;
|
|
29
|
+
export type IsolateFeatures = {
|
|
30
|
+
[IsolateKeys.AllowReorder]?: boolean;
|
|
31
|
+
[IsolateKeys.Transient]?: boolean;
|
|
32
|
+
[IsolateKeys.Status]?: IsolateStatus;
|
|
33
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { CB } from 'vest-utils';
|
|
2
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { TIsolate, Isolate } from '../Isolate';
|
|
5
|
+
import { StateRefType, useAvailableRoot } from '../../VestRuntime';
|
|
6
|
+
import { IsolateMutator, VestRuntime, IReconciler } from '../../vestjs-runtime';
|
|
7
|
+
|
|
8
|
+
enum IsolateType {
|
|
9
|
+
Isolate = 'Isolate',
|
|
10
|
+
Child = 'Child',
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
describe('Isolate', () => {
|
|
14
|
+
let stateRef: StateRefType;
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
stateRef = VestRuntime.createRef({} as IReconciler, v => v);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('Isolate.create', () => {
|
|
21
|
+
it('should return an instance of Isolate', () => {
|
|
22
|
+
const isolate = withRunTime(() => {
|
|
23
|
+
return Isolate.create(IsolateType.Isolate, () => {});
|
|
24
|
+
});
|
|
25
|
+
expect(isolate).toBeInstanceOf(Object);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('Should run the passed callback', () => {
|
|
29
|
+
const spy = vi.fn();
|
|
30
|
+
withRunTime(() => {
|
|
31
|
+
Isolate.create(IsolateType.Isolate, spy);
|
|
32
|
+
});
|
|
33
|
+
expect(spy).toHaveBeenCalled();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('Should store the callback result in the output property', () => {
|
|
37
|
+
const isolate = withRunTime(() => {
|
|
38
|
+
return Isolate.create(
|
|
39
|
+
IsolateType.Isolate,
|
|
40
|
+
() => {
|
|
41
|
+
return 'foo';
|
|
42
|
+
},
|
|
43
|
+
{},
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
expect(isolate.output).toBe('foo');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('When there is no parent', () => {
|
|
50
|
+
it('Parent should be null', () => {
|
|
51
|
+
const isolate = withRunTime(() => {
|
|
52
|
+
return Isolate.create(IsolateType.Isolate, () => {});
|
|
53
|
+
});
|
|
54
|
+
expect(isolate.parent).toBeNull();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('Should set the history root to the current isolate', () => {
|
|
58
|
+
const isolate = withRunTime(() => {
|
|
59
|
+
const isolate = Isolate.create(IsolateType.Isolate, () => {});
|
|
60
|
+
|
|
61
|
+
expect(useAvailableRoot()).toBe(isolate);
|
|
62
|
+
|
|
63
|
+
return isolate;
|
|
64
|
+
});
|
|
65
|
+
// Just verifying that we did not throw and catch inside the runtime
|
|
66
|
+
expect(isolate).toBeDefined();
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('When there is a parent', () => {
|
|
71
|
+
it('Should add the isolate to the parent children', () => {
|
|
72
|
+
const [parent, children] = withRunTime(() => {
|
|
73
|
+
const children = [] as TIsolate[];
|
|
74
|
+
const parent = Isolate.create(IsolateType.Isolate, () => {
|
|
75
|
+
children.push(Isolate.create(IsolateType.Child, () => {}));
|
|
76
|
+
children.push(Isolate.create(IsolateType.Child, () => {}));
|
|
77
|
+
children.push(Isolate.create(IsolateType.Child, () => {}));
|
|
78
|
+
children.push(Isolate.create(IsolateType.Child, () => {}));
|
|
79
|
+
});
|
|
80
|
+
return [parent, children];
|
|
81
|
+
});
|
|
82
|
+
expect(parent.children).toEqual(children);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('Should set the parent property', () => {
|
|
86
|
+
const [parent, child] = withRunTime(() => {
|
|
87
|
+
let child = {} as TIsolate;
|
|
88
|
+
const parent = Isolate.create(IsolateType.Isolate, () => {
|
|
89
|
+
child = Isolate.create(IsolateType.Child, () => null);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return [parent, child];
|
|
93
|
+
});
|
|
94
|
+
expect(child.parent).toBe(parent);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('AbortController', () => {
|
|
100
|
+
it('Should be initially null', () => {
|
|
101
|
+
const isolate = withRunTime(() => {
|
|
102
|
+
return Isolate.create(IsolateType.Isolate, () => {});
|
|
103
|
+
});
|
|
104
|
+
expect(isolate.abortController).toBeNull();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('Should abort the controller with the passed reason', () => {
|
|
108
|
+
const isolate = withRunTime(() => {
|
|
109
|
+
return Isolate.create(IsolateType.Isolate, () => {});
|
|
110
|
+
});
|
|
111
|
+
isolate.abortController = new AbortController();
|
|
112
|
+
const spy = vi.spyOn(isolate.abortController, 'abort');
|
|
113
|
+
IsolateMutator.abort(isolate, 'foo');
|
|
114
|
+
expect(spy).toHaveBeenCalledWith('foo');
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
function withRunTime<T>(fn: CB<T>) {
|
|
119
|
+
return VestRuntime.Run(stateRef, () => {
|
|
120
|
+
return fn();
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
});
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { CB } from 'vest-utils';
|
|
3
|
+
|
|
4
|
+
import { IReconciler } from '../../Reconciler';
|
|
5
|
+
import {
|
|
6
|
+
IsolateFocused,
|
|
7
|
+
FocusModes,
|
|
8
|
+
FocusSelectors,
|
|
9
|
+
VestIsolateTypeFocused,
|
|
10
|
+
} from '../IsolateFocused';
|
|
11
|
+
import * as VestRuntime from '../../VestRuntime';
|
|
12
|
+
import { IsolateKeys } from '../IsolateKeys';
|
|
13
|
+
import { Isolate } from '../Isolate';
|
|
14
|
+
|
|
15
|
+
describe('IsolateFocused', () => {
|
|
16
|
+
function withRunTime<T>(fn: CB<T>) {
|
|
17
|
+
return VestRuntime.Run(
|
|
18
|
+
VestRuntime.createRef((() => null) as unknown as IReconciler, v => v),
|
|
19
|
+
() => fn(),
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe('Focus Modes', () => {
|
|
24
|
+
it('Should expose ONLY and SKIP focus modes', () => {
|
|
25
|
+
expect(FocusModes.ONLY).toBe('only');
|
|
26
|
+
expect(FocusModes.SKIP).toBe('skip');
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe('Isolate creation', () => {
|
|
31
|
+
it('Should return undefined if no fields are provided and matchAll is false', () => {
|
|
32
|
+
let node: any;
|
|
33
|
+
withRunTime(() => {
|
|
34
|
+
Isolate.create('Root', () => {
|
|
35
|
+
node = IsolateFocused(FocusModes.ONLY, []);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
expect(node).toBeUndefined();
|
|
39
|
+
|
|
40
|
+
let node2: any;
|
|
41
|
+
withRunTime(() => {
|
|
42
|
+
Isolate.create('Root', () => {
|
|
43
|
+
node2 = IsolateFocused(FocusModes.ONLY);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
expect(node2).toBeUndefined();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('Should create a focused isolate when matchAll is true', () => {
|
|
50
|
+
let node: any;
|
|
51
|
+
withRunTime(() => {
|
|
52
|
+
Isolate.create('Root', () => {
|
|
53
|
+
node = IsolateFocused(FocusModes.SKIP, true);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
expect(node[IsolateKeys.Type]).toBe(VestIsolateTypeFocused);
|
|
57
|
+
expect(node[IsolateKeys.Transient]).toBe(true);
|
|
58
|
+
expect(node.data).toEqual({
|
|
59
|
+
focusMode: FocusModes.SKIP,
|
|
60
|
+
match: [],
|
|
61
|
+
matchAll: true,
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('Should create a focused isolate with specified fields', () => {
|
|
66
|
+
let node: any;
|
|
67
|
+
withRunTime(() => {
|
|
68
|
+
Isolate.create('Root', () => {
|
|
69
|
+
node = IsolateFocused(FocusModes.ONLY, ['field1', 'field2']);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
expect(node[IsolateKeys.Type]).toBe(VestIsolateTypeFocused);
|
|
73
|
+
expect(node[IsolateKeys.Transient]).toBe(true);
|
|
74
|
+
expect(node.data).toEqual({
|
|
75
|
+
focusMode: FocusModes.ONLY,
|
|
76
|
+
match: ['field1', 'field2'],
|
|
77
|
+
matchAll: false,
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe('FocusSelectors', () => {
|
|
83
|
+
describe('isIsolateFocused', () => {
|
|
84
|
+
it('Should correctly identify a focused isolate', () => {
|
|
85
|
+
let node: any;
|
|
86
|
+
withRunTime(() => {
|
|
87
|
+
Isolate.create('Root', () => {
|
|
88
|
+
node = IsolateFocused(FocusModes.ONLY, ['field1']);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
expect(FocusSelectors.isIsolateFocused(node)).toBe(true);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('Should return false for non-focused isolates', () => {
|
|
95
|
+
let node: any;
|
|
96
|
+
withRunTime(() => {
|
|
97
|
+
node = Isolate.create('Root', () => {});
|
|
98
|
+
});
|
|
99
|
+
expect(FocusSelectors.isIsolateFocused(node)).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
describe('isSkipFocused', () => {
|
|
104
|
+
it('Should return false if focus is undefined', () => {
|
|
105
|
+
expect(FocusSelectors.isSkipFocused(undefined, 'field1')).toBe(false);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('Should return false if focus mode is missing or not SKIP', () => {
|
|
109
|
+
let node: any;
|
|
110
|
+
withRunTime(() => {
|
|
111
|
+
Isolate.create('Root', () => {
|
|
112
|
+
node = IsolateFocused(FocusModes.ONLY, ['field1']);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
expect(FocusSelectors.isSkipFocused(node, 'field1')).toBe(false);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('Should return true if focus is SKIP and matchAll is true', () => {
|
|
119
|
+
let node: any;
|
|
120
|
+
withRunTime(() => {
|
|
121
|
+
Isolate.create('Root', () => {
|
|
122
|
+
node = IsolateFocused(FocusModes.SKIP, true);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
expect(FocusSelectors.isSkipFocused(node)).toBe(true);
|
|
126
|
+
expect(FocusSelectors.isSkipFocused(node, 'anyField')).toBe(true);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('Should return true if focus is SKIP and matches the fieldName', () => {
|
|
130
|
+
let node: any;
|
|
131
|
+
withRunTime(() => {
|
|
132
|
+
Isolate.create('Root', () => {
|
|
133
|
+
node = IsolateFocused(FocusModes.SKIP, ['field1']);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
expect(FocusSelectors.isSkipFocused(node, 'field1')).toBe(true);
|
|
137
|
+
expect(FocusSelectors.isSkipFocused(node, 'field2')).toBe(false);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('Should return true if no fieldName is provided but matches exist', () => {
|
|
141
|
+
let node: any;
|
|
142
|
+
withRunTime(() => {
|
|
143
|
+
Isolate.create('Root', () => {
|
|
144
|
+
node = IsolateFocused(FocusModes.SKIP, ['field1']);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
expect(FocusSelectors.isSkipFocused(node)).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('isOnlyFocused', () => {
|
|
152
|
+
it('Should return false if focus is undefined', () => {
|
|
153
|
+
expect(FocusSelectors.isOnlyFocused(undefined, 'field1')).toBe(false);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('Should return false if focus mode is missing or not ONLY', () => {
|
|
157
|
+
let node: any;
|
|
158
|
+
withRunTime(() => {
|
|
159
|
+
Isolate.create('Root', () => {
|
|
160
|
+
node = IsolateFocused(FocusModes.SKIP, ['field1']);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
expect(FocusSelectors.isOnlyFocused(node, 'field1')).toBe(false);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('Should return true if focus is ONLY and matches the fieldName', () => {
|
|
167
|
+
let node: any;
|
|
168
|
+
withRunTime(() => {
|
|
169
|
+
Isolate.create('Root', () => {
|
|
170
|
+
node = IsolateFocused(FocusModes.ONLY, ['field1', 'field2']);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
expect(FocusSelectors.isOnlyFocused(node, 'field1')).toBe(true);
|
|
174
|
+
expect(FocusSelectors.isOnlyFocused(node, 'field3')).toBe(false);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('Should return true if focus is ONLY and matchAll is true', () => {
|
|
178
|
+
let node: any;
|
|
179
|
+
withRunTime(() => {
|
|
180
|
+
Isolate.create('Root', () => {
|
|
181
|
+
node = IsolateFocused(FocusModes.ONLY, true);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
expect(FocusSelectors.isOnlyFocused(node)).toBe(true);
|
|
185
|
+
expect(FocusSelectors.isOnlyFocused(node, 'anyField')).toBe(true);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('Should return true if no fieldName is provided but matches exist', () => {
|
|
189
|
+
let node: any;
|
|
190
|
+
withRunTime(() => {
|
|
191
|
+
Isolate.create('Root', () => {
|
|
192
|
+
node = IsolateFocused(FocusModes.ONLY, ['field1']);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
expect(FocusSelectors.isOnlyFocused(node)).toBe(true);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
});
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { TIsolate } from '../Isolate';
|
|
4
|
+
import { IsolateInspector } from '../IsolateInspector';
|
|
5
|
+
|
|
6
|
+
describe('IsolateInspector', () => {
|
|
7
|
+
describe('at', () => {
|
|
8
|
+
describe('When the isolate is nullish', () => {
|
|
9
|
+
it('Should return null', () => {
|
|
10
|
+
expect(IsolateInspector.at(null, 0)).toBeNull();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe('When the children are nullish', () => {
|
|
15
|
+
it('Should return null', () => {
|
|
16
|
+
const isolate = { children: null } as unknown as TIsolate;
|
|
17
|
+
|
|
18
|
+
expect(IsolateInspector.at(isolate, 0)).toBeNull();
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('When the child does not exist', () => {
|
|
23
|
+
it('Should return null', () => {
|
|
24
|
+
const isolate = { children: [] } as unknown as TIsolate;
|
|
25
|
+
|
|
26
|
+
expect(IsolateInspector.at(isolate, 0)).toBeNull();
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe('When the child exists', () => {
|
|
31
|
+
it('Should return the child', () => {
|
|
32
|
+
const child = {} as TIsolate;
|
|
33
|
+
const child1 = {} as TIsolate;
|
|
34
|
+
const isolate = { children: [child, child1] } as unknown as TIsolate;
|
|
35
|
+
|
|
36
|
+
expect(IsolateInspector.at(isolate, 0)).toBe(child);
|
|
37
|
+
expect(IsolateInspector.at(isolate, 1)).toBe(child1);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('cursor', () => {
|
|
43
|
+
describe('When the isolate is nullish', () => {
|
|
44
|
+
it('Should return 0', () => {
|
|
45
|
+
expect(IsolateInspector.cursor(null)).toBe(0);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('When the children are nullish', () => {
|
|
50
|
+
it('Should return 0', () => {
|
|
51
|
+
const isolate = { children: null } as unknown as TIsolate;
|
|
52
|
+
|
|
53
|
+
expect(IsolateInspector.cursor(isolate)).toBe(0);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('When the children exist', () => {
|
|
58
|
+
it('Should return the length of the children', () => {
|
|
59
|
+
const child = {} as TIsolate;
|
|
60
|
+
const child1 = {} as TIsolate;
|
|
61
|
+
const isolate = { children: [child, child1] } as unknown as TIsolate;
|
|
62
|
+
|
|
63
|
+
expect(IsolateInspector.cursor(isolate)).toBe(2);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('canReorder', () => {
|
|
69
|
+
describe('When the isolate is nullish', () => {
|
|
70
|
+
it('Should return false', () => {
|
|
71
|
+
expect(IsolateInspector.canReorder(null)).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('When the isolate does not allow reordering', () => {
|
|
76
|
+
it('Should return false', () => {
|
|
77
|
+
const isolate = { allowReorder: false } as unknown as TIsolate;
|
|
78
|
+
|
|
79
|
+
expect(IsolateInspector.canReorder(isolate)).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('When the isolate does not allow reordering but a parent does', () => {
|
|
84
|
+
it('Should return true', () => {
|
|
85
|
+
const root = { allowReorder: false } as unknown as TIsolate;
|
|
86
|
+
const parent = {
|
|
87
|
+
allowReorder: true,
|
|
88
|
+
parent: root,
|
|
89
|
+
} as unknown as TIsolate;
|
|
90
|
+
const isolate = { allowReorder: false, parent } as unknown as TIsolate;
|
|
91
|
+
|
|
92
|
+
expect(IsolateInspector.canReorder(isolate)).toBe(true);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe('When only the root allows reordering', () => {
|
|
96
|
+
it('Should return false', () => {
|
|
97
|
+
const root = { allowReorder: true } as unknown as TIsolate;
|
|
98
|
+
const parent = {
|
|
99
|
+
allowReorder: false,
|
|
100
|
+
parent: root,
|
|
101
|
+
} as unknown as TIsolate;
|
|
102
|
+
const isolate = {
|
|
103
|
+
allowReorder: false,
|
|
104
|
+
parent,
|
|
105
|
+
} as unknown as TIsolate;
|
|
106
|
+
|
|
107
|
+
expect(IsolateInspector.canReorder(isolate)).toBe(false);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe('usesKey', () => {
|
|
114
|
+
describe('When the node is nullish', () => {
|
|
115
|
+
it('Should return false', () => {
|
|
116
|
+
expect(IsolateInspector.usesKey(null)).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe('When the node does not have a key', () => {
|
|
121
|
+
it('Should return false', () => {
|
|
122
|
+
const isolate = { key: null } as unknown as TIsolate;
|
|
123
|
+
|
|
124
|
+
expect(IsolateInspector.usesKey(isolate)).toBe(false);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('When the node has a key', () => {
|
|
129
|
+
it('Should return true', () => {
|
|
130
|
+
const isolate = { key: 'key' } as unknown as TIsolate;
|
|
131
|
+
|
|
132
|
+
expect(IsolateInspector.usesKey(isolate)).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
});
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { TIsolate } from '../Isolate';
|
|
2
|
+
import { IsolateMutator } from '../IsolateMutator';
|
|
3
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
4
|
+
|
|
5
|
+
describe('IsolateMutator', () => {
|
|
6
|
+
describe('setParent', () => {
|
|
7
|
+
it('should set parent', () => {
|
|
8
|
+
const parent = {} as TIsolate;
|
|
9
|
+
const isolate = {} as TIsolate;
|
|
10
|
+
|
|
11
|
+
expect(isolate.parent).toBeUndefined();
|
|
12
|
+
expect(IsolateMutator.setParent(isolate, parent)).toBe(isolate);
|
|
13
|
+
expect(isolate.parent).toBe(parent);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe('When the child already has a parent', () => {
|
|
17
|
+
it('Should set the new parent of the child', () => {
|
|
18
|
+
const parent1 = {} as TIsolate;
|
|
19
|
+
const parent2 = {} as TIsolate;
|
|
20
|
+
const isolate = {} as TIsolate;
|
|
21
|
+
|
|
22
|
+
IsolateMutator.setParent(isolate, parent1);
|
|
23
|
+
expect(isolate.parent).toBe(parent1);
|
|
24
|
+
IsolateMutator.setParent(isolate, parent2);
|
|
25
|
+
expect(isolate.parent).toBe(parent2);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe('saveOutput', () => {
|
|
31
|
+
it('should save output', () => {
|
|
32
|
+
const isolate = {} as TIsolate;
|
|
33
|
+
const output = {};
|
|
34
|
+
|
|
35
|
+
expect(isolate.output).toBeUndefined();
|
|
36
|
+
expect(IsolateMutator.saveOutput(isolate, output)).toBe(isolate);
|
|
37
|
+
expect(isolate.output).toBe(output);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('setKey', () => {
|
|
42
|
+
it('should set key', () => {
|
|
43
|
+
const isolate = {} as TIsolate;
|
|
44
|
+
const key = 'foo';
|
|
45
|
+
|
|
46
|
+
expect(isolate.key).toBeUndefined();
|
|
47
|
+
expect(IsolateMutator.setKey(isolate, key)).toBe(isolate);
|
|
48
|
+
expect(isolate.key).toBe(key);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('addChild', () => {
|
|
53
|
+
it('should add child', () => {
|
|
54
|
+
const isolate = { children: [] } as unknown as TIsolate;
|
|
55
|
+
const child1 = {} as TIsolate;
|
|
56
|
+
const child2 = {} as TIsolate;
|
|
57
|
+
|
|
58
|
+
expect(isolate.children).toEqual([]);
|
|
59
|
+
IsolateMutator.addChild(isolate, child1);
|
|
60
|
+
expect(isolate.children).toEqual([child1]);
|
|
61
|
+
IsolateMutator.addChild(isolate, child2);
|
|
62
|
+
expect(isolate.children).toEqual([child1, child2]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should set parent of the child', () => {
|
|
66
|
+
const isolate = { children: [] } as unknown as TIsolate;
|
|
67
|
+
const child = {} as TIsolate;
|
|
68
|
+
|
|
69
|
+
expect(child.parent).toBeUndefined();
|
|
70
|
+
IsolateMutator.addChild(isolate, child);
|
|
71
|
+
expect(child.parent).toBe(isolate);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('removeChild', () => {
|
|
76
|
+
it('Should remove child', () => {
|
|
77
|
+
const child1 = {} as TIsolate;
|
|
78
|
+
const child2 = {} as TIsolate;
|
|
79
|
+
const isolate = { children: [child1, child2] } as unknown as TIsolate;
|
|
80
|
+
|
|
81
|
+
expect(isolate.children).toEqual([child1, child2]);
|
|
82
|
+
IsolateMutator.removeChild(isolate, child1);
|
|
83
|
+
expect(isolate.children).toEqual([child2]);
|
|
84
|
+
IsolateMutator.removeChild(isolate, child2);
|
|
85
|
+
expect(isolate.children).toEqual([]);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('When the child does not exist', () => {
|
|
89
|
+
it('Should no-op', () => {
|
|
90
|
+
const child = {} as TIsolate;
|
|
91
|
+
const isolate = { children: [] } as unknown as TIsolate;
|
|
92
|
+
|
|
93
|
+
expect(isolate.children).toEqual([]);
|
|
94
|
+
IsolateMutator.removeChild(isolate, child);
|
|
95
|
+
expect(isolate.children).toEqual([]);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe('slice', () => {
|
|
101
|
+
it('Should slice children', () => {
|
|
102
|
+
const child1 = {} as TIsolate;
|
|
103
|
+
const child2 = {} as TIsolate;
|
|
104
|
+
const isolate = { children: [child1, child2] } as unknown as TIsolate;
|
|
105
|
+
|
|
106
|
+
expect(isolate.children).toEqual([child1, child2]);
|
|
107
|
+
IsolateMutator.slice(isolate, 1);
|
|
108
|
+
expect(isolate.children).toEqual([child1]);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('When children are nullish', () => {
|
|
112
|
+
it('Should no-op', () => {
|
|
113
|
+
const isolate = { children: null } as unknown as TIsolate;
|
|
114
|
+
|
|
115
|
+
expect(isolate.children).toBeNull();
|
|
116
|
+
IsolateMutator.slice(isolate, 1);
|
|
117
|
+
expect(isolate.children).toBeNull();
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
describe('abort', () => {
|
|
123
|
+
it('Should abort the controller', () => {
|
|
124
|
+
const isolate = {
|
|
125
|
+
abortController: { abort: vi.fn() },
|
|
126
|
+
} as unknown as TIsolate;
|
|
127
|
+
|
|
128
|
+
expect(isolate.abortController!.abort).not.toHaveBeenCalled();
|
|
129
|
+
IsolateMutator.abort(isolate);
|
|
130
|
+
expect(isolate.abortController!.abort).toHaveBeenCalled();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
describe('When the controller is nullish', () => {
|
|
134
|
+
it('Should no-op', () => {
|
|
135
|
+
const isolate = { abortController: null } as unknown as TIsolate;
|
|
136
|
+
|
|
137
|
+
expect(isolate.abortController).toBeNull();
|
|
138
|
+
IsolateMutator.abort(isolate);
|
|
139
|
+
expect(isolate.abortController).toBeNull();
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('Should abort the controller with the passed reason', () => {
|
|
144
|
+
const isolate = {
|
|
145
|
+
abortController: { abort: vi.fn() },
|
|
146
|
+
} as unknown as TIsolate;
|
|
147
|
+
|
|
148
|
+
expect(isolate.abortController!.abort).not.toHaveBeenCalled();
|
|
149
|
+
IsolateMutator.abort(isolate, 'foo');
|
|
150
|
+
expect(isolate.abortController!.abort).toHaveBeenCalledWith('foo');
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe('setData', () => {
|
|
155
|
+
it('Should set the data', () => {
|
|
156
|
+
const isolate = {} as TIsolate;
|
|
157
|
+
const data = { foo: 'bar' };
|
|
158
|
+
|
|
159
|
+
expect(isolate.data).toBeUndefined();
|
|
160
|
+
IsolateMutator.setData(isolate, data);
|
|
161
|
+
expect(isolate.data).toBe(data);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
});
|