@ryupold/vode 1.8.7 → 1.8.10
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/README.md +34 -56
- package/dist/vode.cjs.min.js +2 -2
- package/dist/vode.d.ts +10 -10
- package/dist/vode.es5.min.js +7 -7
- package/dist/vode.js +97 -113
- package/dist/vode.min.js +1 -1
- package/dist/vode.min.mjs +1 -1
- package/dist/vode.mjs +97 -113
- package/dist/vode.tests.mjs +5303 -0
- package/package.json +5 -5
- package/src/state-context.ts +6 -4
- package/src/vode.ts +114 -126
- package/test/helper.ts +304 -113
- package/test/index.ts +10 -47
- package/test/mocks.ts +199 -43
- package/test/run-tests.ts +61 -0
- package/test/tests-app.ts +154 -38
- package/test/tests-catch.ts +160 -0
- package/test/tests-children.ts +31 -31
- package/test/tests-createPatch.ts +12 -12
- package/test/tests-createState.ts +11 -11
- package/test/tests-defuse.ts +35 -14
- package/test/tests-examples.ts +991 -0
- package/test/tests-hydrate.ts +59 -25
- package/test/tests-memo.ts +106 -64
- package/test/tests-mergeClass.ts +31 -31
- package/test/tests-mergeProps.ts +19 -19
- package/test/tests-mergeStyle.ts +28 -14
- package/test/tests-mount-unmount.ts +177 -154
- package/test/tests-patch-advanced.ts +86 -0
- package/test/tests-patch-merge.ts +66 -0
- package/test/tests-props.ts +15 -15
- package/test/tests-state-context.ts +56 -25
- package/test/tests-tag.ts +14 -14
- package/test/tests-vode.ts +6 -6
package/test/tests-app.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { expect } from "./helper";
|
|
2
|
-
import { app, ARTICLE, DIV, P, SPAN } from "../index";
|
|
2
|
+
import { app, ARTICLE, BUTTON, createState, DIV, P, SPAN, SECTION } from "../index";
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
|
-
"app(): successful initialization": () => {
|
|
5
|
+
"app(): successful initialization": async () => {
|
|
6
6
|
const root = document.createElement("div");
|
|
7
7
|
const container = document.createElement("div");
|
|
8
8
|
root.appendChild(container);
|
|
@@ -19,7 +19,7 @@ export default {
|
|
|
19
19
|
|
|
20
20
|
expect(patch).toBeA("function");
|
|
21
21
|
|
|
22
|
-
expect(container).toMatch(
|
|
22
|
+
await expect(container).toMatch(
|
|
23
23
|
[DIV,
|
|
24
24
|
[ARTICLE,
|
|
25
25
|
[P, "foo", [SPAN, "bar"]]
|
|
@@ -30,15 +30,15 @@ export default {
|
|
|
30
30
|
|
|
31
31
|
//=== FAILURE CASES ===
|
|
32
32
|
|
|
33
|
-
"app(): fails when the container has no parent": () => {
|
|
33
|
+
"app(): fails when the container has no parent": async () => {
|
|
34
34
|
const container = document.createElement("div");
|
|
35
35
|
const err = expect(() => app(container, {}, () => [DIV]))
|
|
36
36
|
.toFail();
|
|
37
37
|
|
|
38
|
-
expect(err.message).toEqual("first argument to app() must be a valid HTMLElement inside the <html></html> document");
|
|
38
|
+
await expect(err.message).toEqual("first argument to app() must be a valid HTMLElement inside the <html></html> document");
|
|
39
39
|
},
|
|
40
40
|
|
|
41
|
-
"app(): fails when the state is not an object": () => {
|
|
41
|
+
"app(): fails when the state is not an object": async () => {
|
|
42
42
|
const root = document.createElement("div");
|
|
43
43
|
const container = document.createElement("div");
|
|
44
44
|
root.appendChild(container);
|
|
@@ -46,10 +46,10 @@ export default {
|
|
|
46
46
|
const err = expect(() => app(container, "oops", () => [DIV]))
|
|
47
47
|
.toFail();
|
|
48
48
|
|
|
49
|
-
expect(err.message).toEqual("second argument to app() must be a state object");
|
|
49
|
+
await expect(err.message).toEqual("second argument to app() must be a state object");
|
|
50
50
|
},
|
|
51
51
|
|
|
52
|
-
"app(): fails when the dom factory is not a function": () => {
|
|
52
|
+
"app(): fails when the dom factory is not a function": async () => {
|
|
53
53
|
const root = document.createElement("div");
|
|
54
54
|
const container = document.createElement("div");
|
|
55
55
|
root.appendChild(container);
|
|
@@ -57,12 +57,12 @@ export default {
|
|
|
57
57
|
const err = expect(() => app(container, {}, [DIV] as any))
|
|
58
58
|
.toFail();
|
|
59
59
|
|
|
60
|
-
expect(err.message).toEqual("third argument to app() must be a function that returns a vode");
|
|
60
|
+
await expect(err.message).toEqual("third argument to app() must be a function that returns a vode");
|
|
61
61
|
},
|
|
62
62
|
|
|
63
63
|
//=== INITIAL PATCHES ===
|
|
64
64
|
|
|
65
|
-
"app(): executes initial patches after first render": () => {
|
|
65
|
+
"app(): executes initial patches after first render": async () => {
|
|
66
66
|
const root = document.createElement("div");
|
|
67
67
|
const container = document.createElement("div");
|
|
68
68
|
root.appendChild(container);
|
|
@@ -74,12 +74,12 @@ export default {
|
|
|
74
74
|
() => ({ start: 2 })
|
|
75
75
|
);
|
|
76
76
|
|
|
77
|
-
expect(state).toEqual({ count: 7, start: 2 });
|
|
77
|
+
await expect(state).toEqual({ count: 7, start: 2 });
|
|
78
78
|
},
|
|
79
79
|
|
|
80
80
|
//=== STATE PATCHING ===
|
|
81
81
|
|
|
82
|
-
"app(): patch with object updates state and re-renders DOM": () => {
|
|
82
|
+
"app(): patch with object updates state and re-renders DOM": async () => {
|
|
83
83
|
const root = document.createElement("div");
|
|
84
84
|
const container = document.createElement("div");
|
|
85
85
|
root.appendChild(container);
|
|
@@ -87,16 +87,16 @@ export default {
|
|
|
87
87
|
const state: any = { msg: "hello" };
|
|
88
88
|
app(container, state, (s: any) => [DIV, s.msg]);
|
|
89
89
|
|
|
90
|
-
expect(state.msg).toEqual("hello");
|
|
91
|
-
expect(container).toMatch([DIV, "hello"]);
|
|
90
|
+
await expect(state.msg).toEqual("hello");
|
|
91
|
+
await expect(container).toMatch([DIV, "hello"]);
|
|
92
92
|
|
|
93
93
|
state.patch({ msg: "world" });
|
|
94
94
|
|
|
95
|
-
expect(state.msg).toEqual("world");
|
|
96
|
-
expect(container).toMatch([DIV, "world"]);
|
|
95
|
+
await expect(state.msg).toEqual("world");
|
|
96
|
+
await expect(container).toMatch([DIV, "world"]);
|
|
97
97
|
},
|
|
98
98
|
|
|
99
|
-
"app(): patch with effect function executes and applies result": () => {
|
|
99
|
+
"app(): patch with effect function executes and applies result": async () => {
|
|
100
100
|
const root = document.createElement("div");
|
|
101
101
|
const container = document.createElement("div");
|
|
102
102
|
root.appendChild(container);
|
|
@@ -106,11 +106,11 @@ export default {
|
|
|
106
106
|
|
|
107
107
|
state.patch(() => ({ count: 5 }));
|
|
108
108
|
|
|
109
|
-
expect(state.count).toEqual(5);
|
|
110
|
-
expect(container).toMatch([DIV, "5"]);
|
|
109
|
+
await expect(state.count).toEqual(5);
|
|
110
|
+
await expect(container).toMatch([DIV, "5"]);
|
|
111
111
|
},
|
|
112
112
|
|
|
113
|
-
"app(): patch with array applies multiple patches in sequence": () => {
|
|
113
|
+
"app(): patch with array applies multiple patches in sequence": async () => {
|
|
114
114
|
const root = document.createElement("div");
|
|
115
115
|
const container = document.createElement("div");
|
|
116
116
|
root.appendChild(container);
|
|
@@ -118,13 +118,13 @@ export default {
|
|
|
118
118
|
const state: any = { a: 1, b: 2 };
|
|
119
119
|
app(container, state, () => [DIV]);
|
|
120
120
|
|
|
121
|
-
state.patch([{ a: 10 }, { b: 20 }]);
|
|
121
|
+
await state.patch([{ a: 10 }, { b: 20 }]);
|
|
122
122
|
|
|
123
|
-
expect(state.a).toEqual(10);
|
|
124
|
-
expect(state.b).toEqual(20);
|
|
123
|
+
await expect(state.a).toEqual(10);
|
|
124
|
+
await expect(state.b).toEqual(20);
|
|
125
125
|
},
|
|
126
126
|
|
|
127
|
-
"app(): multiple sequential patches both apply": () => {
|
|
127
|
+
"app(): multiple sequential patches both apply": async () => {
|
|
128
128
|
const root = document.createElement("div");
|
|
129
129
|
const container = document.createElement("div");
|
|
130
130
|
root.appendChild(container);
|
|
@@ -135,12 +135,12 @@ export default {
|
|
|
135
135
|
state.patch({ x: 1 });
|
|
136
136
|
state.patch({ y: 2 });
|
|
137
137
|
|
|
138
|
-
expect(state).toEqual({ x: 1, y: 2 });
|
|
138
|
+
await expect(state).toEqual({ x: 1, y: 2 });
|
|
139
139
|
},
|
|
140
140
|
|
|
141
141
|
//=== LIFECYCLE ===
|
|
142
142
|
|
|
143
|
-
"app(): onMount callback is called on newly created child elements": () => {
|
|
143
|
+
"app(): onMount callback is called on newly created child elements": async () => {
|
|
144
144
|
const root = document.createElement("div");
|
|
145
145
|
const container = document.createElement("div");
|
|
146
146
|
root.appendChild(container);
|
|
@@ -152,12 +152,12 @@ export default {
|
|
|
152
152
|
] as any
|
|
153
153
|
);
|
|
154
154
|
|
|
155
|
-
expect(mountCalled).toEqual(true);
|
|
155
|
+
await expect(mountCalled).toEqual(true);
|
|
156
156
|
},
|
|
157
157
|
|
|
158
158
|
//=== COMPONENTS ===
|
|
159
159
|
|
|
160
|
-
"app(): component function as child renders correctly": () => {
|
|
160
|
+
"app(): component function as child renders correctly": async () => {
|
|
161
161
|
const root = document.createElement("div");
|
|
162
162
|
const container = document.createElement("div");
|
|
163
163
|
root.appendChild(container);
|
|
@@ -168,12 +168,12 @@ export default {
|
|
|
168
168
|
]
|
|
169
169
|
);
|
|
170
170
|
|
|
171
|
-
expect(container).toMatch(
|
|
171
|
+
await expect(container).toMatch(
|
|
172
172
|
[DIV, [SPAN, "component rendered"]]
|
|
173
173
|
);
|
|
174
174
|
},
|
|
175
175
|
|
|
176
|
-
"app(): component accesses state and renders dynamic content": () => {
|
|
176
|
+
"app(): component accesses state and renders dynamic content": async () => {
|
|
177
177
|
const root = document.createElement("div");
|
|
178
178
|
const container = document.createElement("div");
|
|
179
179
|
root.appendChild(container);
|
|
@@ -185,12 +185,12 @@ export default {
|
|
|
185
185
|
]
|
|
186
186
|
);
|
|
187
187
|
|
|
188
|
-
expect(container).toMatch([DIV, [SPAN, "dynamic"]]);
|
|
188
|
+
await expect(container).toMatch([DIV, [SPAN, "dynamic"]]);
|
|
189
189
|
},
|
|
190
190
|
|
|
191
191
|
//=== DEEP STATE ===
|
|
192
192
|
|
|
193
|
-
"app(): deep nested state merges correctly via patch": () => {
|
|
193
|
+
"app(): deep nested state merges correctly via patch": async () => {
|
|
194
194
|
const root = document.createElement("div");
|
|
195
195
|
const container = document.createElement("div");
|
|
196
196
|
root.appendChild(container);
|
|
@@ -200,14 +200,14 @@ export default {
|
|
|
200
200
|
|
|
201
201
|
state.patch({ nested: { value: 2 } });
|
|
202
202
|
|
|
203
|
-
expect(state.nested.value).toEqual(2);
|
|
204
|
-
expect(state.nested.other).toEqual("keep");
|
|
205
|
-
expect(container).toMatch([DIV, "2"]);
|
|
203
|
+
await expect(state.nested.value).toEqual(2);
|
|
204
|
+
await expect(state.nested.other).toEqual("keep");
|
|
205
|
+
await expect(container).toMatch([DIV, "2"]);
|
|
206
206
|
},
|
|
207
207
|
|
|
208
208
|
//=== IGNORED PATCHES ===
|
|
209
209
|
|
|
210
|
-
"app(): patching with ignored types is a no-op": () => {
|
|
210
|
+
"app(): patching with ignored types is a no-op": async () => {
|
|
211
211
|
const root = document.createElement("div");
|
|
212
212
|
const container = document.createElement("div");
|
|
213
213
|
root.appendChild(container);
|
|
@@ -221,6 +221,122 @@ export default {
|
|
|
221
221
|
state.patch("ignored");
|
|
222
222
|
state.patch(true);
|
|
223
223
|
|
|
224
|
-
expect(state.x).toEqual(1);
|
|
224
|
+
await expect(state.x).toEqual(1);
|
|
225
225
|
},
|
|
226
|
-
|
|
226
|
+
|
|
227
|
+
"app(): isolated state of multiple independent vode app instances": async () => {
|
|
228
|
+
const root = document.createElement("div");
|
|
229
|
+
|
|
230
|
+
// APP 1 (foo) //
|
|
231
|
+
const containerFoo = document.createElement("div");
|
|
232
|
+
root.appendChild(containerFoo);
|
|
233
|
+
const stateFoo = createState({ count: 0 });
|
|
234
|
+
const patchFoo = app<typeof stateFoo>(containerFoo, stateFoo, (s) => [
|
|
235
|
+
DIV,
|
|
236
|
+
[P, `App 1 count: ${s.count}`],
|
|
237
|
+
[BUTTON, {
|
|
238
|
+
onclick: () => {
|
|
239
|
+
// sync state2 from app1 via the returned patch function
|
|
240
|
+
patchBar({ count: stateBar.count + 1 });
|
|
241
|
+
return { count: s.count + 1 };
|
|
242
|
+
}
|
|
243
|
+
}, "Sync +1"],
|
|
244
|
+
]);
|
|
245
|
+
/////////////////
|
|
246
|
+
|
|
247
|
+
// APP 2 (bar) //
|
|
248
|
+
const containerBar = document.createElement("div");
|
|
249
|
+
root.appendChild(containerBar);
|
|
250
|
+
const stateBar = createState({ count: 0 });
|
|
251
|
+
const patchBar = app<typeof stateBar>(containerBar, stateBar, (s) => [
|
|
252
|
+
DIV,
|
|
253
|
+
[P, `App 2 count: ${s.count}`],
|
|
254
|
+
]);
|
|
255
|
+
/////////////////
|
|
256
|
+
|
|
257
|
+
await expect(containerFoo).toMatch(
|
|
258
|
+
[DIV,
|
|
259
|
+
[P, "App 1 count: 0"],
|
|
260
|
+
[BUTTON, "Sync +1"],
|
|
261
|
+
]
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
await expect(containerBar).toMatch(
|
|
265
|
+
[DIV,
|
|
266
|
+
[P, "App 2 count: 0"],
|
|
267
|
+
]
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
// Patch state1 independently: no effect on state2
|
|
271
|
+
patchFoo({ count: 5 });
|
|
272
|
+
|
|
273
|
+
await expect(containerFoo).toMatch(
|
|
274
|
+
[DIV,
|
|
275
|
+
[P, "App 1 count: 5"],
|
|
276
|
+
[BUTTON, "Sync +1"],
|
|
277
|
+
]
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
await expect(containerBar).toMatch(
|
|
281
|
+
[DIV,
|
|
282
|
+
[P, "App 2 count: 0"],
|
|
283
|
+
]
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
// Patch state2 independently: no effect on state1
|
|
287
|
+
patchBar({ count: 3 });
|
|
288
|
+
|
|
289
|
+
await expect(containerFoo).toMatch(
|
|
290
|
+
[DIV,
|
|
291
|
+
[P, "App 1 count: 5"],
|
|
292
|
+
[BUTTON, "Sync +1"],
|
|
293
|
+
]
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
await expect(containerBar).toMatch(
|
|
297
|
+
[DIV,
|
|
298
|
+
[P, "App 2 count: 3"],
|
|
299
|
+
]
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
// Sync state2 via the returned patch function
|
|
303
|
+
patchBar({ count: 10 });
|
|
304
|
+
|
|
305
|
+
await expect(containerBar).toMatch(
|
|
306
|
+
[DIV,
|
|
307
|
+
[P, "App 2 count: 10"],
|
|
308
|
+
]
|
|
309
|
+
);
|
|
310
|
+
},
|
|
311
|
+
|
|
312
|
+
"app(): root tag changes between renders": async () => {
|
|
313
|
+
const root = document.createElement("div");
|
|
314
|
+
const container = document.createElement("div");
|
|
315
|
+
root.appendChild(container);
|
|
316
|
+
const state = createState({ useSection: false });
|
|
317
|
+
|
|
318
|
+
const patch = app<typeof state>(container, state, (s) =>
|
|
319
|
+
s.useSection ? [SECTION, "section mode"] : [DIV, "div mode"]
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
await expect(container).toMatch([DIV, "div mode"]);
|
|
323
|
+
|
|
324
|
+
patch({ useSection: true });
|
|
325
|
+
|
|
326
|
+
await expect(root).toMatch([DIV, [SECTION, "section mode"]]);
|
|
327
|
+
},
|
|
328
|
+
|
|
329
|
+
"app(): event handler with object patch": () => {
|
|
330
|
+
const root = document.createElement("div");
|
|
331
|
+
const container = document.createElement("div");
|
|
332
|
+
root.appendChild(container);
|
|
333
|
+
const state: any = { count: 0 };
|
|
334
|
+
|
|
335
|
+
app(container, state, (s: any) =>
|
|
336
|
+
[DIV, { onclick: { count: 42 } }, "click me"]
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
const el = (container as any)._vode.vode.node;
|
|
340
|
+
expect(el.onclick).toBeA("function");
|
|
341
|
+
},
|
|
342
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { expect } from "./helper";
|
|
2
|
+
import { app, createState, DIV, ARTICLE, SECTION, P } from "../index";
|
|
3
|
+
|
|
4
|
+
function setup() {
|
|
5
|
+
const root = document.createElement("div");
|
|
6
|
+
const container = document.createElement("div");
|
|
7
|
+
root.appendChild(container);
|
|
8
|
+
return container;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
"catch: function fallback renders instead of broken component": async () => {
|
|
13
|
+
const container = setup();
|
|
14
|
+
const broken = () => { throw new Error("boom"); };
|
|
15
|
+
|
|
16
|
+
app(container, {}, () =>
|
|
17
|
+
[DIV,
|
|
18
|
+
[SECTION,
|
|
19
|
+
{ catch: (s: unknown, err: Error) => [P, `caught: ${err.message}`] },
|
|
20
|
+
broken
|
|
21
|
+
]
|
|
22
|
+
]
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
await expect(container).toMatch(
|
|
26
|
+
[DIV,
|
|
27
|
+
[P, "caught: boom"]
|
|
28
|
+
]
|
|
29
|
+
);
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
"catch: static vode fallback renders instead of broken component": async () => {
|
|
33
|
+
const container = setup();
|
|
34
|
+
const broken = () => { throw new Error("boom"); };
|
|
35
|
+
|
|
36
|
+
app(container, {}, () =>
|
|
37
|
+
[DIV,
|
|
38
|
+
[SECTION,
|
|
39
|
+
{ catch: [ARTICLE, "error occurred"] },
|
|
40
|
+
broken
|
|
41
|
+
]
|
|
42
|
+
]
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
await expect(container).toMatch(
|
|
46
|
+
[DIV,
|
|
47
|
+
[ARTICLE, "error occurred"]
|
|
48
|
+
]
|
|
49
|
+
);
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
"catch: nested error boundaries — inner catch handles inner error": async () => {
|
|
53
|
+
const container = setup();
|
|
54
|
+
const broken = () => { throw new Error("inner boom"); };
|
|
55
|
+
|
|
56
|
+
app(container, {}, () =>
|
|
57
|
+
[DIV,
|
|
58
|
+
[SECTION,
|
|
59
|
+
[P,
|
|
60
|
+
{
|
|
61
|
+
catch: [ARTICLE, "inner fallback"]
|
|
62
|
+
},
|
|
63
|
+
broken
|
|
64
|
+
]
|
|
65
|
+
]
|
|
66
|
+
]
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
await expect(container).toMatch(
|
|
70
|
+
[DIV,
|
|
71
|
+
[SECTION,
|
|
72
|
+
[ARTICLE, "inner fallback"]
|
|
73
|
+
]
|
|
74
|
+
]
|
|
75
|
+
);
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
"catch: nested error boundaries — outer catches when inner has no handler": async () => {
|
|
79
|
+
const container = setup();
|
|
80
|
+
const broken = () => { throw new Error("boom"); };
|
|
81
|
+
|
|
82
|
+
app(container, {}, () =>
|
|
83
|
+
[DIV,
|
|
84
|
+
[SECTION,
|
|
85
|
+
{ catch: [P, "outer caught it"] },
|
|
86
|
+
[ARTICLE, broken]
|
|
87
|
+
]
|
|
88
|
+
]
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
await expect(container).toMatch(
|
|
92
|
+
[DIV,
|
|
93
|
+
[P, "outer caught it"]
|
|
94
|
+
]
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
"catch: error propagates when no handler exists on entire tree": async () => {
|
|
99
|
+
const container = setup();
|
|
100
|
+
const broken = () => { throw new Error("crash"); };
|
|
101
|
+
let threw = false;
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
app(container, {}, () =>
|
|
105
|
+
[DIV, [P, broken]]
|
|
106
|
+
);
|
|
107
|
+
} catch {
|
|
108
|
+
threw = true;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
await expect(threw).toEqual(true);
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
"catch: catch handler changed on A→A path": async () => {
|
|
115
|
+
const container = setup();
|
|
116
|
+
const state = createState({ catchValue: "v1", showBroken: false });
|
|
117
|
+
const broken = () => { throw new Error("boom"); };
|
|
118
|
+
|
|
119
|
+
const patch = app<typeof state>(container, state, (s) =>
|
|
120
|
+
[DIV,
|
|
121
|
+
[SECTION,
|
|
122
|
+
{ catch: [P, s.catchValue] },
|
|
123
|
+
s.showBroken ? broken : "ok"
|
|
124
|
+
]
|
|
125
|
+
]
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
await expect(container).toMatch(
|
|
129
|
+
[DIV, [SECTION, "ok"]]
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
patch({ catchValue: "v2", showBroken: true });
|
|
133
|
+
|
|
134
|
+
await expect(container).toMatch(
|
|
135
|
+
[DIV, [P, "v2"]]
|
|
136
|
+
);
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
"catch: error in one sibling doesn't affect the other": async () => {
|
|
140
|
+
const container = setup();
|
|
141
|
+
const broken = () => { throw new Error("boom"); };
|
|
142
|
+
|
|
143
|
+
app(container, {}, () =>
|
|
144
|
+
[DIV,
|
|
145
|
+
[SECTION,
|
|
146
|
+
{ catch: [P, "whoops"] },
|
|
147
|
+
broken
|
|
148
|
+
],
|
|
149
|
+
[ARTICLE, "i am fine"]
|
|
150
|
+
]
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
await expect(container).toMatch(
|
|
154
|
+
[DIV,
|
|
155
|
+
[P, "whoops"],
|
|
156
|
+
[ARTICLE, "i am fine"]
|
|
157
|
+
]
|
|
158
|
+
);
|
|
159
|
+
},
|
|
160
|
+
};
|
package/test/tests-children.ts
CHANGED
|
@@ -2,68 +2,68 @@ import { children, child, childCount, childrenStart, DIV, SPAN, P, Vode } from "
|
|
|
2
2
|
import { expect } from "./helper";
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
|
-
"children(): tag+props+children returns children array": () => {
|
|
5
|
+
"children(): tag+props+children returns children array": async () => {
|
|
6
6
|
const v: Vode = [DIV, { class: "x" }, [SPAN, "a"], [P, "b"]];
|
|
7
7
|
const c = children(v);
|
|
8
|
-
expect(Array.isArray(c)).toEqual(true);
|
|
9
|
-
expect(c!.length).toEqual(2);
|
|
8
|
+
await expect(Array.isArray(c)).toEqual(true);
|
|
9
|
+
await expect(c!.length).toEqual(2);
|
|
10
10
|
},
|
|
11
11
|
|
|
12
|
-
"children(): tag+children (no props) returns children array": () => {
|
|
12
|
+
"children(): tag+children (no props) returns children array": async () => {
|
|
13
13
|
const v: Vode = [DIV, [SPAN, "a"], [P, "b"]];
|
|
14
14
|
const c = children(v);
|
|
15
|
-
expect(Array.isArray(c)).toEqual(true);
|
|
16
|
-
expect(c!.length).toEqual(2);
|
|
15
|
+
await expect(Array.isArray(c)).toEqual(true);
|
|
16
|
+
await expect(c!.length).toEqual(2);
|
|
17
17
|
},
|
|
18
18
|
|
|
19
|
-
"children(): just-tag vode returns null": () => {
|
|
20
|
-
expect(children([DIV])).toEqual(null);
|
|
19
|
+
"children(): just-tag vode returns null": async () => {
|
|
20
|
+
await expect(children([DIV])).toEqual(null);
|
|
21
21
|
},
|
|
22
22
|
|
|
23
|
-
"children(): text vode returns null": () => {
|
|
24
|
-
expect(children("hello")).toEqual(null);
|
|
23
|
+
"children(): text vode returns null": async () => {
|
|
24
|
+
await expect(children("hello")).toEqual(null);
|
|
25
25
|
},
|
|
26
26
|
|
|
27
|
-
"childrenStart(): with props+children returns 2": () => {
|
|
28
|
-
expect(childrenStart([DIV, { class: "x" }, [SPAN]])).toEqual(2);
|
|
27
|
+
"childrenStart(): with props+children returns 2": async () => {
|
|
28
|
+
await expect(childrenStart([DIV, { class: "x" }, [SPAN]])).toEqual(2);
|
|
29
29
|
},
|
|
30
30
|
|
|
31
|
-
"childrenStart(): without props but with children returns 1": () => {
|
|
32
|
-
expect(childrenStart([DIV, [SPAN]])).toEqual(1);
|
|
31
|
+
"childrenStart(): without props but with children returns 1": async () => {
|
|
32
|
+
await expect(childrenStart([DIV, [SPAN]])).toEqual(1);
|
|
33
33
|
},
|
|
34
34
|
|
|
35
|
-
"childrenStart(): just-tag returns -1": () => {
|
|
36
|
-
expect(childrenStart([DIV])).toEqual(-1);
|
|
35
|
+
"childrenStart(): just-tag returns -1": async () => {
|
|
36
|
+
await expect(childrenStart([DIV])).toEqual(-1);
|
|
37
37
|
},
|
|
38
38
|
|
|
39
|
-
"childrenStart(): text vode returns -1": () => {
|
|
40
|
-
expect(childrenStart("hello")).toEqual(-1);
|
|
39
|
+
"childrenStart(): text vode returns -1": async () => {
|
|
40
|
+
await expect(childrenStart("hello")).toEqual(-1);
|
|
41
41
|
},
|
|
42
42
|
|
|
43
|
-
"childCount(): matches actual child count": () => {
|
|
44
|
-
expect(childCount([DIV, { class: "x" }, [SPAN, "a"], [P, "b"]])).toEqual(2);
|
|
45
|
-
expect(childCount([DIV, [SPAN]])).toEqual(1);
|
|
43
|
+
"childCount(): matches actual child count": async () => {
|
|
44
|
+
await expect(childCount([DIV, { class: "x" }, [SPAN, "a"], [P, "b"]])).toEqual(2);
|
|
45
|
+
await expect(childCount([DIV, [SPAN]])).toEqual(1);
|
|
46
46
|
},
|
|
47
47
|
|
|
48
|
-
"childCount(): returns 0 for no-children vode": () => {
|
|
49
|
-
expect(childCount([DIV])).toEqual(0);
|
|
50
|
-
expect(childCount("hello" as any)).toEqual(0);
|
|
48
|
+
"childCount(): returns 0 for no-children vode": async () => {
|
|
49
|
+
await expect(childCount([DIV])).toEqual(0);
|
|
50
|
+
await expect(childCount("hello" as any)).toEqual(0);
|
|
51
51
|
},
|
|
52
52
|
|
|
53
|
-
"child(): returns correct child at index": () => {
|
|
53
|
+
"child(): returns correct child at index": async () => {
|
|
54
54
|
const v: Vode = [DIV, { class: "x" }, [SPAN, "a"], [P, "b"]];
|
|
55
55
|
|
|
56
|
-
expect(child(v, 0)).toEqual([SPAN, "a"]);
|
|
57
|
-
expect(child(v, 1)).toEqual([P, "b"]);
|
|
56
|
+
await expect(child(v, 0)).toEqual([SPAN, "a"]);
|
|
57
|
+
await expect(child(v, 1)).toEqual([P, "b"]);
|
|
58
58
|
},
|
|
59
59
|
|
|
60
|
-
"child(): returns undefined for out-of-bounds": () => {
|
|
61
|
-
expect(child([DIV, { class: "x" }, [SPAN]], 5))
|
|
60
|
+
"child(): returns undefined for out-of-bounds": async () => {
|
|
61
|
+
await expect(child([DIV, { class: "x" }, [SPAN]], 5))
|
|
62
62
|
.toEqual(undefined);
|
|
63
63
|
},
|
|
64
64
|
|
|
65
|
-
"child(): returns undefined for text vode": () => {
|
|
66
|
-
expect(child("hello" as any, 0))
|
|
65
|
+
"child(): returns undefined for text vode": async () => {
|
|
66
|
+
await expect(child("hello" as any, 0))
|
|
67
67
|
.toEqual(undefined);
|
|
68
68
|
}
|
|
69
69
|
};
|
|
@@ -2,27 +2,27 @@ import { createPatch } from "../src/vode";
|
|
|
2
2
|
import { expect } from "./helper";
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
|
-
"createPatch(): just returns the input": () => {
|
|
5
|
+
"createPatch(): just returns the input": async () => {
|
|
6
6
|
const p = { a: 123 };
|
|
7
|
-
expect(createPatch(p) === p).toEqual(true);
|
|
7
|
+
await expect(createPatch(p) === p).toEqual(true);
|
|
8
8
|
},
|
|
9
9
|
|
|
10
|
-
"createPatch(): returns undefined as-is": () => {
|
|
11
|
-
expect(createPatch(undefined)).toEqual(undefined);
|
|
10
|
+
"createPatch(): returns undefined as-is": async () => {
|
|
11
|
+
await expect(createPatch(undefined)).toEqual(undefined);
|
|
12
12
|
},
|
|
13
13
|
|
|
14
|
-
"createPatch(): returns null as-is": () => {
|
|
15
|
-
expect(createPatch(null)).toEqual(null);
|
|
14
|
+
"createPatch(): returns null as-is": async () => {
|
|
15
|
+
await expect(createPatch(null)).toEqual(null);
|
|
16
16
|
},
|
|
17
17
|
|
|
18
|
-
"createPatch(): returns function as-is": () => {
|
|
18
|
+
"createPatch(): returns function as-is": async () => {
|
|
19
19
|
const fn = () => ({});
|
|
20
|
-
expect(createPatch(fn) === fn).toEqual(true);
|
|
20
|
+
await expect(createPatch(fn) === fn).toEqual(true);
|
|
21
21
|
},
|
|
22
22
|
|
|
23
|
-
"createPatch(): returns primitive as-is": () => {
|
|
24
|
-
expect(createPatch(42)).toEqual(42);
|
|
25
|
-
expect(createPatch("ignored")).toEqual("ignored");
|
|
26
|
-
expect(createPatch(false)).toEqual(false);
|
|
23
|
+
"createPatch(): returns primitive as-is": async () => {
|
|
24
|
+
await expect(createPatch(42)).toEqual(42);
|
|
25
|
+
await expect(createPatch("ignored")).toEqual("ignored");
|
|
26
|
+
await expect(createPatch(false)).toEqual(false);
|
|
27
27
|
}
|
|
28
28
|
};
|