@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.
@@ -1,17 +1,9 @@
1
1
  import { expect } from "./helper";
2
- import { context, ProxySubContext } from "../src/state-context";
2
+ import { context } from "../src/state-context";
3
3
  import { createState } from "../src/vode";
4
4
 
5
5
  export default {
6
- "StateContext.state: returns the state reference": async () => {
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
- "StateContext.get(): deep nested": async () => {
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
- "StateContext.get(): missing nested path returns undefined": async () => {
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
- "StateContext.put(): silently mutates state": async () => {
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
- "StateContext.put() on nested object replaces the sub-object": async () => {
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
- "StateContext.put() at root level with empty keys": async () => {
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
- "StateContext.patch(): calls state.patch with proper deep partial": async () => {
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
- "StateContext.patch(): async wraps in array": async () => {
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
- "StateContext.patch() on nested deep path three levels": async () => {
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
- "StateContext.put() with intermediate null creates objects along the path": async () => {
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
- "StateContext.put() with three-level intermediate null": async () => {
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
- "StateContext.put() with multiple intermediate nulls": async () => {
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
  };