@ryupold/vode 1.8.11 → 1.9.0
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/dist/vode.cjs.min.js +3 -3
- package/dist/vode.d.ts +23 -25
- package/dist/vode.es5.min.js +6 -6
- package/dist/vode.js +32 -9
- package/dist/vode.min.js +1 -1
- package/dist/vode.min.mjs +1 -1
- package/dist/vode.mjs +32 -9
- package/dist/vode.tests.mjs +281 -45
- package/package.json +4 -4
- package/src/merge-class.ts +3 -3
- package/src/state-context.ts +65 -38
- package/src/vode.ts +10 -3
- package/test/helper.ts +1 -1
- package/test/tests-app.ts +42 -2
- package/test/tests-catch.ts +61 -1
- package/test/tests-examples.ts +3 -3
- package/test/tests-mergeClass.ts +11 -4
- package/test/tests-mergeProps.ts +5 -0
- package/test/tests-patch-advanced.ts +20 -21
- package/test/tests-state-context.ts +181 -21
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import { expect } from "./helper";
|
|
2
|
-
import { context
|
|
2
|
+
import { context } from "../src/state-context";
|
|
3
3
|
import { createState } from "../src/vode";
|
|
4
4
|
|
|
5
5
|
export default {
|
|
6
|
-
"
|
|
7
|
-
const state = createState({ x: 10 });
|
|
8
|
-
const ctx = context(state);
|
|
9
|
-
|
|
10
|
-
await expect((ctx).state === state)
|
|
11
|
-
.toEqual(true);
|
|
12
|
-
},
|
|
13
|
-
|
|
14
|
-
"StateContext.get() returns whole state": async () => {
|
|
6
|
+
"context(s)...get(): returns whole state": async () => {
|
|
15
7
|
const state = createState({ a: 1, b: 2 });
|
|
16
8
|
const ctx = context(state);
|
|
17
9
|
|
|
@@ -20,7 +12,7 @@ export default {
|
|
|
20
12
|
},
|
|
21
13
|
|
|
22
14
|
|
|
23
|
-
"
|
|
15
|
+
"context(s)...get(): deep nested": async () => {
|
|
24
16
|
const state = createState({ a: { b: { c: 42 } } });
|
|
25
17
|
const ctx = context(state);
|
|
26
18
|
|
|
@@ -28,7 +20,7 @@ export default {
|
|
|
28
20
|
.toEqual(42);
|
|
29
21
|
},
|
|
30
22
|
|
|
31
|
-
"
|
|
23
|
+
"context(s)...get(): missing nested path returns undefined": async () => {
|
|
32
24
|
const state = createState({ a: {} });
|
|
33
25
|
const ctx = context(state);
|
|
34
26
|
|
|
@@ -36,7 +28,7 @@ export default {
|
|
|
36
28
|
.toEqual(undefined);
|
|
37
29
|
},
|
|
38
30
|
|
|
39
|
-
"
|
|
31
|
+
"context(s)...put(): silently mutates state": async () => {
|
|
40
32
|
const state = createState({ a: { b: 1 } });
|
|
41
33
|
const ctx = context(state);
|
|
42
34
|
ctx.a.b.put(2);
|
|
@@ -45,7 +37,7 @@ export default {
|
|
|
45
37
|
.toEqual(2);
|
|
46
38
|
},
|
|
47
39
|
|
|
48
|
-
"
|
|
40
|
+
"context(s)...put(): on nested object replaces the sub-object": async () => {
|
|
49
41
|
const state = createState({ a: { b: { x: 1, y: 2 } } });
|
|
50
42
|
const ctx = context(state);
|
|
51
43
|
ctx.a.b.put({ y: 99 });
|
|
@@ -54,7 +46,7 @@ export default {
|
|
|
54
46
|
.toEqual({ y: 99 });
|
|
55
47
|
},
|
|
56
48
|
|
|
57
|
-
"
|
|
49
|
+
"context(s)...put(): at root level with empty keys": async () => {
|
|
58
50
|
const state = createState({ a: 1, b: 2 });
|
|
59
51
|
const ctx = context(state);
|
|
60
52
|
ctx.put({ b: undefined });
|
|
@@ -63,7 +55,7 @@ export default {
|
|
|
63
55
|
.toEqual({ a: 1 });
|
|
64
56
|
},
|
|
65
57
|
|
|
66
|
-
"
|
|
58
|
+
"context(s)...patch(): calls state.patch with proper deep partial": async () => {
|
|
67
59
|
const state = createState({ a: { b: 1 } });
|
|
68
60
|
const ctx = context(state);
|
|
69
61
|
ctx.a.b.patch(2);
|
|
@@ -76,7 +68,7 @@ export default {
|
|
|
76
68
|
.toEqual({ a: { b: 2 } });
|
|
77
69
|
},
|
|
78
70
|
|
|
79
|
-
"
|
|
71
|
+
"context(s)...patch(): async wraps in array": async () => {
|
|
80
72
|
const state = createState({ a: { b: 1 } });
|
|
81
73
|
const ctx = context(state);
|
|
82
74
|
ctx.a.b.patch(2, true);
|
|
@@ -91,7 +83,7 @@ export default {
|
|
|
91
83
|
.toEqual({ a: { b: 2 } });
|
|
92
84
|
},
|
|
93
85
|
|
|
94
|
-
"
|
|
86
|
+
"context(s)...patch(): on nested deep path three levels": async () => {
|
|
95
87
|
const state = createState({ x: { y: { z: 0 } } });
|
|
96
88
|
const ctx = context(state);
|
|
97
89
|
ctx.x.y.z.patch(100);
|
|
@@ -104,7 +96,7 @@ export default {
|
|
|
104
96
|
.toEqual({ x: { y: { z: 100 } } });
|
|
105
97
|
},
|
|
106
98
|
|
|
107
|
-
"
|
|
99
|
+
"context(s)...put(): with intermediate null creates objects along the path": async () => {
|
|
108
100
|
const state = createState({ a: null as { b: number } | null });
|
|
109
101
|
const ctx = context(state);
|
|
110
102
|
|
|
@@ -116,7 +108,7 @@ export default {
|
|
|
116
108
|
await expect(state.a?.b).toEqual(undefined);
|
|
117
109
|
},
|
|
118
110
|
|
|
119
|
-
"
|
|
111
|
+
"context(s)...put(): with three-level intermediate null": async () => {
|
|
120
112
|
const state = createState({ a: null as { b: { c: number } } | null });
|
|
121
113
|
const ctx = context(state);
|
|
122
114
|
|
|
@@ -125,7 +117,7 @@ export default {
|
|
|
125
117
|
await expect(state.a?.b.c).toEqual(99);
|
|
126
118
|
},
|
|
127
119
|
|
|
128
|
-
"
|
|
120
|
+
"context(s)...put(): with multiple intermediate nulls": async () => {
|
|
129
121
|
const state = createState({ a: { x: null as { z: string } | null, y: 1 } });
|
|
130
122
|
const ctx = context(state);
|
|
131
123
|
|
|
@@ -134,4 +126,172 @@ export default {
|
|
|
134
126
|
await expect(state.a.x?.z).toEqual("deep");
|
|
135
127
|
await expect(state.a.y).toEqual(1);
|
|
136
128
|
},
|
|
129
|
+
|
|
130
|
+
"context(s)...put(): merges into existing object properties via Object.assign": async () => {
|
|
131
|
+
const state = createState({ items: { count: 0, name: "test", hidden: false } });
|
|
132
|
+
const ctx = context(state);
|
|
133
|
+
ctx.items.put({ count: 5 });
|
|
134
|
+
await expect(state.items).toEqual({ count: 5, name: "test", hidden: false });
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
"context(state, s => s).get(): returns whole state": async () => {
|
|
138
|
+
const state = createState({ a: 1, b: 2 });
|
|
139
|
+
const ctx = context(state, s => s);
|
|
140
|
+
|
|
141
|
+
await expect(ctx.get())
|
|
142
|
+
.toEqual({ a: 1, b: 2 });
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
"context(state, s => s.a.b.c).get(): deep nested": async () => {
|
|
146
|
+
const state = createState({ a: { b: { c: 42 } } });
|
|
147
|
+
const ctx = context(state, s => s.a.b.c);
|
|
148
|
+
|
|
149
|
+
await expect(ctx.get())
|
|
150
|
+
.toEqual(42);
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
"context(state, s => s.a.b).get(): missing nested path returns undefined": async () => {
|
|
154
|
+
const state = createState({ a: {} });
|
|
155
|
+
const ctx = context(state, s => (s.a as any).b);
|
|
156
|
+
|
|
157
|
+
await expect(ctx.get())
|
|
158
|
+
.toEqual(undefined);
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
"context(state, s => s.a.b).put(): silently mutates state": async () => {
|
|
162
|
+
const state = createState({ a: { b: 1 } });
|
|
163
|
+
const ctx = context(state, s => s.a.b);
|
|
164
|
+
ctx.put(2);
|
|
165
|
+
|
|
166
|
+
await expect(state.a.b)
|
|
167
|
+
.toEqual(2);
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
"context(state, s => s.a.b).put(): on nested object replaces the sub-object": async () => {
|
|
171
|
+
const state = createState({ a: { b: { x: 1, y: 2 } } });
|
|
172
|
+
const ctx = context(state, s => s.a.b);
|
|
173
|
+
ctx.put({ y: 99 });
|
|
174
|
+
|
|
175
|
+
await expect(state.a.b)
|
|
176
|
+
.toEqual({ y: 99 });
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
"context(state, s => s).put(): at root level with empty keys": async () => {
|
|
180
|
+
const state = createState({ a: 1, b: 2 });
|
|
181
|
+
const ctx = context(state, s => s);
|
|
182
|
+
ctx.put({ b: undefined });
|
|
183
|
+
|
|
184
|
+
await expect(state)
|
|
185
|
+
.toEqual({ a: 1 });
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
"context(state, s => s.a.b).patch(): calls state.patch with proper deep partial": async () => {
|
|
189
|
+
const state = createState({ a: { b: 1 } });
|
|
190
|
+
const ctx = context(state, s => s.a.b);
|
|
191
|
+
ctx.patch(2);
|
|
192
|
+
|
|
193
|
+
const patches = (state as any).patch.initialPatches;
|
|
194
|
+
|
|
195
|
+
await expect(patches.length)
|
|
196
|
+
.toEqual(1);
|
|
197
|
+
await expect(patches[0])
|
|
198
|
+
.toEqual({ a: { b: 2 } });
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
"context(state, s => s.a.b).patch(): async wraps in array": async () => {
|
|
202
|
+
const state = createState({ a: { b: 1 } });
|
|
203
|
+
const ctx = context(state, s => s.a.b);
|
|
204
|
+
ctx.patch(2, true);
|
|
205
|
+
|
|
206
|
+
const patches = (state as any).patch.initialPatches;
|
|
207
|
+
|
|
208
|
+
await expect(patches.length)
|
|
209
|
+
.toEqual(1);
|
|
210
|
+
await expect(Array.isArray(patches[0]))
|
|
211
|
+
.toEqual(true);
|
|
212
|
+
await expect(patches[0][0])
|
|
213
|
+
.toEqual({ a: { b: 2 } });
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
"context(state, s => s.x.y.z).patch(): on nested deep path three levels": async () => {
|
|
217
|
+
const state = createState({ x: { y: { z: 0 } } });
|
|
218
|
+
const ctx = context(state, s => s.x.y.z);
|
|
219
|
+
ctx.patch(100);
|
|
220
|
+
|
|
221
|
+
const patches = (state as any).patch.initialPatches;
|
|
222
|
+
|
|
223
|
+
await expect(patches.length)
|
|
224
|
+
.toEqual(1);
|
|
225
|
+
await expect(patches[0])
|
|
226
|
+
.toEqual({ x: { y: { z: 100 } } });
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
"context(state, s => s.x).y.z: continue proxy sub-state targeting": async () => {
|
|
230
|
+
const state = createState({ x: { y: { z: 0 } } });
|
|
231
|
+
const ctx = context(state, s => s.x).y.z;
|
|
232
|
+
ctx.patch(100);
|
|
233
|
+
|
|
234
|
+
const patches = (state as any).patch.initialPatches;
|
|
235
|
+
|
|
236
|
+
await expect(patches.length)
|
|
237
|
+
.toEqual(1);
|
|
238
|
+
await expect(patches[0])
|
|
239
|
+
.toEqual({ x: { y: { z: 100 } } });
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
"context(state, s => s.a.b).put(): with intermediate null creates objects": async () => {
|
|
243
|
+
const state = createState({ a: null as { b: number } | null });
|
|
244
|
+
const ctx = context(state, s => s.a.b);
|
|
245
|
+
|
|
246
|
+
ctx.put(42);
|
|
247
|
+
await expect(state.a?.b).toEqual(42);
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
"context(state, s => s.a.b.c).put(): with three-level intermediate null": async () => {
|
|
251
|
+
const state = createState({ a: null as { b: { c: number } } | null });
|
|
252
|
+
const ctx = context(state, s => s.a.b.c);
|
|
253
|
+
|
|
254
|
+
ctx.put(99);
|
|
255
|
+
|
|
256
|
+
await expect(state.a?.b.c).toEqual(99);
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
"context(state, s => s.a.x.z).put(): with multiple intermediate nulls": async () => {
|
|
260
|
+
const state = createState({ a: { x: null as { z: string } | null, y: 1 } });
|
|
261
|
+
const ctx = context(state, s => s.a.x.z);
|
|
262
|
+
|
|
263
|
+
ctx.put("deep");
|
|
264
|
+
|
|
265
|
+
await expect(state.a.x?.z).toEqual("deep");
|
|
266
|
+
await expect(state.a.y).toEqual(1);
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
"context(state, s => s.items).put(): merges into existing object properties via Object.assign": async () => {
|
|
270
|
+
const state = createState({ items: { count: 0, name: "test", hidden: false } });
|
|
271
|
+
const ctx = context(state, s => s.items);
|
|
272
|
+
ctx.put({ count: 5 });
|
|
273
|
+
await expect(state.items).toEqual({ count: 5, name: "test", hidden: false });
|
|
274
|
+
},
|
|
275
|
+
|
|
276
|
+
"context(state, s => s.get|put|patch...): 'get','put','patch' as intermediate properties without conflict": async () => {
|
|
277
|
+
const state = createState({
|
|
278
|
+
endpoints: {
|
|
279
|
+
get: { count: 1 },
|
|
280
|
+
put: { count: 2 },
|
|
281
|
+
patch: { count: 3 }
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
const getCtx = context(state, s => s.endpoints.get);
|
|
286
|
+
await expect(getCtx.get()).toEqual({ count: 1 });
|
|
287
|
+
|
|
288
|
+
const putCtx = context(state, s => s.endpoints.put);
|
|
289
|
+
putCtx.put({ count: 99 });
|
|
290
|
+
await expect(state.endpoints.put).toEqual({ count: 99 });
|
|
291
|
+
|
|
292
|
+
const patchCtx = context(state, s => s.endpoints.patch);
|
|
293
|
+
patchCtx.patch({ count: 42 });
|
|
294
|
+
const patches = (state as any).patch.initialPatches;
|
|
295
|
+
await expect(patches[0]).toEqual({ endpoints: { patch: { count: 42 } } });
|
|
296
|
+
},
|
|
137
297
|
};
|