@ryupold/vode 1.8.8 → 1.8.11
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/.github/workflows/publish.yml +5 -0
- package/.github/workflows/tests.yml +1 -0
- package/README.md +36 -2
- package/dist/vode.cjs.min.js +1 -1
- package/dist/vode.d.ts +5 -6
- package/dist/vode.es5.min.js +1 -1
- package/dist/vode.js +54 -44
- package/dist/vode.min.js +1 -1
- package/dist/vode.min.mjs +1 -1
- package/dist/vode.mjs +54 -44
- package/dist/vode.tests.mjs +5475 -0
- package/log.txt +1 -0
- package/package.json +5 -5
- package/src/vode.ts +63 -52
- package/test/helper.ts +299 -146
- package/test/index.ts +2 -64
- package/test/mocks.ts +83 -9
- package/test/run-tests.ts +61 -0
- package/test/tests-app.ts +48 -48
- package/test/tests-catch.ts +15 -15
- 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 +18 -18
- package/test/tests-examples.ts +87 -88
- package/test/tests-hydrate.ts +28 -28
- package/test/tests-memo.ts +29 -28
- 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 +368 -268
- package/test/tests-patch-advanced.ts +127 -19
- package/test/tests-patch-merge.ts +15 -15
- package/test/tests-props.ts +15 -15
- package/test/tests-state-context.ts +33 -33
- package/test/tests-tag.ts +14 -14
- package/test/tests-vode.ts +6 -6
package/test/mocks.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { globals } from "../src/vode";
|
|
2
|
+
|
|
1
3
|
const NodeConstants = {
|
|
2
4
|
ELEMENT_NODE: 1,
|
|
3
5
|
ATTRIBUTE_NODE: 2,
|
|
@@ -181,14 +183,40 @@ export class FakeTextNode {
|
|
|
181
183
|
}
|
|
182
184
|
|
|
183
185
|
export function resetMocks() {
|
|
184
|
-
|
|
186
|
+
let hidden = false;
|
|
187
|
+
let rafHandle = 0;
|
|
188
|
+
const rafQueue = new Map<number, FrameRequestCallback>();
|
|
189
|
+
let rafTimer: ReturnType<typeof setTimeout> | null = null;
|
|
190
|
+
|
|
191
|
+
function scheduleNextFrame() {
|
|
192
|
+
if (rafTimer !== null || hidden || rafQueue.size === 0) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
rafTimer = setTimeout(() => {
|
|
197
|
+
rafTimer = null;
|
|
198
|
+
|
|
199
|
+
if (hidden || rafQueue.size === 0) {
|
|
200
|
+
scheduleNextFrame();
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const now = performance.now();
|
|
205
|
+
const callbacks = Array.from(rafQueue.values());
|
|
206
|
+
rafQueue.clear();
|
|
207
|
+
|
|
208
|
+
for (const cb of callbacks) {
|
|
209
|
+
cb(now);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
scheduleNextFrame();
|
|
213
|
+
}, 16);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const fakeDocument: any = {
|
|
185
217
|
createElement: (tag: string) => new FakeElement(tag),
|
|
186
218
|
createTextNode: (text: string) => new FakeTextNode(text),
|
|
187
219
|
createElementNS: (ns: string, tag: string) => new FakeElement(tag),
|
|
188
|
-
hidden: false,
|
|
189
|
-
};
|
|
190
|
-
const mockWin: any = {
|
|
191
|
-
requestAnimationFrame: (cb: any) => cb(Date.now()),
|
|
192
220
|
startViewTransition: (callbackOptions: any) => {
|
|
193
221
|
return {
|
|
194
222
|
finished: Promise.resolve(),
|
|
@@ -196,10 +224,56 @@ export function resetMocks() {
|
|
|
196
224
|
updateCallbackDone: Promise.resolve(),
|
|
197
225
|
skipTransition() { },
|
|
198
226
|
};
|
|
199
|
-
}
|
|
227
|
+
},
|
|
228
|
+
_fake: true,
|
|
200
229
|
};
|
|
201
230
|
|
|
202
|
-
|
|
203
|
-
|
|
231
|
+
Object.defineProperty(fakeDocument, "hidden", {
|
|
232
|
+
enumerable: true,
|
|
233
|
+
configurable: true,
|
|
234
|
+
get: () => hidden,
|
|
235
|
+
set: (value: boolean) => {
|
|
236
|
+
hidden = !!value;
|
|
237
|
+
if (!hidden) {
|
|
238
|
+
scheduleNextFrame();
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
const fakeWindow: any = {
|
|
244
|
+
requestAnimationFrame: (cb: FrameRequestCallback) => {
|
|
245
|
+
const id = ++rafHandle;
|
|
246
|
+
rafQueue.set(id, cb);
|
|
247
|
+
scheduleNextFrame();
|
|
248
|
+
return id;
|
|
249
|
+
},
|
|
250
|
+
cancelAnimationFrame: (id: number) => {
|
|
251
|
+
rafQueue.delete(id);
|
|
252
|
+
},
|
|
253
|
+
_fake: true,
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
if ((<typeof fakeDocument>globalThis.document)?._fake)
|
|
257
|
+
globalThis.document = undefined as any;
|
|
258
|
+
if ((<typeof fakeWindow>globalThis.window)?._fake)
|
|
259
|
+
globalThis.window = undefined as any;
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
globalThis.document ??= fakeDocument as Document;
|
|
263
|
+
globalThis.window ??= fakeWindow as (Window & typeof globalThis);
|
|
204
264
|
globalThis.Node ??= NodeConstants as any;
|
|
205
|
-
|
|
265
|
+
|
|
266
|
+
if ((<typeof fakeWindow>globalThis.window)?._fake) {
|
|
267
|
+
const raf = globalThis.window?.requestAnimationFrame;
|
|
268
|
+
if (typeof raf === "function") {
|
|
269
|
+
globals.requestAnimationFrame = raf.bind(globalThis.window);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if ((<typeof fakeDocument>globalThis.document)?._fake) {
|
|
274
|
+
const startViewTransition = (globalThis.document as any)?.startViewTransition;
|
|
275
|
+
globals.startViewTransition = typeof startViewTransition === "function"
|
|
276
|
+
? startViewTransition.bind(globalThis.document)
|
|
277
|
+
: null;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { tests } from ".";
|
|
2
|
+
import { expect, ExpectationError } from "./helper";
|
|
3
|
+
import { resetMocks } from "./mocks";
|
|
4
|
+
|
|
5
|
+
const count = {
|
|
6
|
+
total: 0,
|
|
7
|
+
passed: 0,
|
|
8
|
+
failed: <string[]>[],
|
|
9
|
+
}
|
|
10
|
+
const line = "----------------------------------";
|
|
11
|
+
|
|
12
|
+
async function runTest(test: [string, () => any]) {
|
|
13
|
+
count.total++;
|
|
14
|
+
resetMocks();
|
|
15
|
+
const start = performance.now();
|
|
16
|
+
try {
|
|
17
|
+
expect(document).toBeNotHidden();
|
|
18
|
+
const result = test[1]();
|
|
19
|
+
if (result && typeof (result as any)?.then === "function") {
|
|
20
|
+
await result;
|
|
21
|
+
}
|
|
22
|
+
count.passed++;
|
|
23
|
+
const time = (performance.now() - start).toFixed(3) + " ms";
|
|
24
|
+
console.log(`#${count.total} ${test[0]}\n-> 🟢 passed ${time}\n${line}`);
|
|
25
|
+
} catch (err: any) {
|
|
26
|
+
const time = (performance.now() - start).toFixed(3) + " ms";
|
|
27
|
+
console.error(`#${count.total} ${test[0]}\n-> 🔴 failed ${time}`);
|
|
28
|
+
if (err instanceof ExpectationError) {
|
|
29
|
+
count.failed.push(`#${count.total} ${test[0]}\n-> 🔴 failed:\n${err.message}\n${line}`);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
count.failed.push(`#${count.total} ${test[0]}\n-> 🔴 failed:\n${err.message}\n${err.stack}\n${line}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const sw = performance.now();
|
|
38
|
+
(async () => {
|
|
39
|
+
for (const test of Object.entries(tests)) {
|
|
40
|
+
await runTest(test);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const time = (performance.now() - sw).toFixed(3) + " ms";
|
|
44
|
+
|
|
45
|
+
console.log(`
|
|
46
|
+
total: ${count.total}
|
|
47
|
+
passed: ${count.passed}
|
|
48
|
+
failed: ${count.failed.length}
|
|
49
|
+
|
|
50
|
+
time: ${time}
|
|
51
|
+
`);
|
|
52
|
+
|
|
53
|
+
if (count.passed === count.total) {
|
|
54
|
+
console.log("\n\nall tests passed\n");
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
console.error(`${line.replaceAll("-", "=")}\nError summary:\n\n${count.failed.join(`\n${line}\n`)}`);
|
|
58
|
+
|
|
59
|
+
throw "\n\nsome tests failed (see output)\n";
|
|
60
|
+
}
|
|
61
|
+
})();
|
package/test/tests-app.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { expect } from "./helper";
|
|
|
2
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,10 +221,10 @@ 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": () => {
|
|
227
|
+
"app(): isolated state of multiple independent vode app instances": async () => {
|
|
228
228
|
const root = document.createElement("div");
|
|
229
229
|
|
|
230
230
|
// APP 1 (foo) //
|
|
@@ -254,14 +254,14 @@ export default {
|
|
|
254
254
|
]);
|
|
255
255
|
/////////////////
|
|
256
256
|
|
|
257
|
-
expect(containerFoo).toMatch(
|
|
257
|
+
await expect(containerFoo).toMatch(
|
|
258
258
|
[DIV,
|
|
259
259
|
[P, "App 1 count: 0"],
|
|
260
260
|
[BUTTON, "Sync +1"],
|
|
261
261
|
]
|
|
262
262
|
);
|
|
263
263
|
|
|
264
|
-
expect(containerBar).toMatch(
|
|
264
|
+
await expect(containerBar).toMatch(
|
|
265
265
|
[DIV,
|
|
266
266
|
[P, "App 2 count: 0"],
|
|
267
267
|
]
|
|
@@ -270,14 +270,14 @@ export default {
|
|
|
270
270
|
// Patch state1 independently: no effect on state2
|
|
271
271
|
patchFoo({ count: 5 });
|
|
272
272
|
|
|
273
|
-
expect(containerFoo).toMatch(
|
|
273
|
+
await expect(containerFoo).toMatch(
|
|
274
274
|
[DIV,
|
|
275
275
|
[P, "App 1 count: 5"],
|
|
276
276
|
[BUTTON, "Sync +1"],
|
|
277
277
|
]
|
|
278
278
|
);
|
|
279
279
|
|
|
280
|
-
expect(containerBar).toMatch(
|
|
280
|
+
await expect(containerBar).toMatch(
|
|
281
281
|
[DIV,
|
|
282
282
|
[P, "App 2 count: 0"],
|
|
283
283
|
]
|
|
@@ -286,14 +286,14 @@ export default {
|
|
|
286
286
|
// Patch state2 independently: no effect on state1
|
|
287
287
|
patchBar({ count: 3 });
|
|
288
288
|
|
|
289
|
-
expect(containerFoo).toMatch(
|
|
289
|
+
await expect(containerFoo).toMatch(
|
|
290
290
|
[DIV,
|
|
291
291
|
[P, "App 1 count: 5"],
|
|
292
292
|
[BUTTON, "Sync +1"],
|
|
293
293
|
]
|
|
294
294
|
);
|
|
295
295
|
|
|
296
|
-
expect(containerBar).toMatch(
|
|
296
|
+
await expect(containerBar).toMatch(
|
|
297
297
|
[DIV,
|
|
298
298
|
[P, "App 2 count: 3"],
|
|
299
299
|
]
|
|
@@ -302,14 +302,14 @@ export default {
|
|
|
302
302
|
// Sync state2 via the returned patch function
|
|
303
303
|
patchBar({ count: 10 });
|
|
304
304
|
|
|
305
|
-
expect(containerBar).toMatch(
|
|
305
|
+
await expect(containerBar).toMatch(
|
|
306
306
|
[DIV,
|
|
307
307
|
[P, "App 2 count: 10"],
|
|
308
308
|
]
|
|
309
309
|
);
|
|
310
310
|
},
|
|
311
311
|
|
|
312
|
-
"app(): root tag changes between renders": () => {
|
|
312
|
+
"app(): root tag changes between renders": async () => {
|
|
313
313
|
const root = document.createElement("div");
|
|
314
314
|
const container = document.createElement("div");
|
|
315
315
|
root.appendChild(container);
|
|
@@ -319,11 +319,11 @@ export default {
|
|
|
319
319
|
s.useSection ? [SECTION, "section mode"] : [DIV, "div mode"]
|
|
320
320
|
);
|
|
321
321
|
|
|
322
|
-
expect(container).toMatch([DIV, "div mode"]);
|
|
322
|
+
await expect(container).toMatch([DIV, "div mode"]);
|
|
323
323
|
|
|
324
324
|
patch({ useSection: true });
|
|
325
325
|
|
|
326
|
-
expect(root).toMatch([DIV, [SECTION, "section mode"]]);
|
|
326
|
+
await expect(root).toMatch([DIV, [SECTION, "section mode"]]);
|
|
327
327
|
},
|
|
328
328
|
|
|
329
329
|
"app(): event handler with object patch": () => {
|
|
@@ -339,4 +339,4 @@ export default {
|
|
|
339
339
|
const el = (container as any)._vode.vode.node;
|
|
340
340
|
expect(el.onclick).toBeA("function");
|
|
341
341
|
},
|
|
342
|
-
};
|
|
342
|
+
};
|
package/test/tests-catch.ts
CHANGED
|
@@ -9,7 +9,7 @@ function setup() {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export default {
|
|
12
|
-
"catch: function fallback renders instead of broken component": () => {
|
|
12
|
+
"catch: function fallback renders instead of broken component": async () => {
|
|
13
13
|
const container = setup();
|
|
14
14
|
const broken = () => { throw new Error("boom"); };
|
|
15
15
|
|
|
@@ -22,14 +22,14 @@ export default {
|
|
|
22
22
|
]
|
|
23
23
|
);
|
|
24
24
|
|
|
25
|
-
expect(container).toMatch(
|
|
25
|
+
await expect(container).toMatch(
|
|
26
26
|
[DIV,
|
|
27
27
|
[P, "caught: boom"]
|
|
28
28
|
]
|
|
29
29
|
);
|
|
30
30
|
},
|
|
31
31
|
|
|
32
|
-
"catch: static vode fallback renders instead of broken component": () => {
|
|
32
|
+
"catch: static vode fallback renders instead of broken component": async () => {
|
|
33
33
|
const container = setup();
|
|
34
34
|
const broken = () => { throw new Error("boom"); };
|
|
35
35
|
|
|
@@ -42,14 +42,14 @@ export default {
|
|
|
42
42
|
]
|
|
43
43
|
);
|
|
44
44
|
|
|
45
|
-
expect(container).toMatch(
|
|
45
|
+
await expect(container).toMatch(
|
|
46
46
|
[DIV,
|
|
47
47
|
[ARTICLE, "error occurred"]
|
|
48
48
|
]
|
|
49
49
|
);
|
|
50
50
|
},
|
|
51
51
|
|
|
52
|
-
"catch: nested error boundaries — inner catch handles inner error": () => {
|
|
52
|
+
"catch: nested error boundaries — inner catch handles inner error": async () => {
|
|
53
53
|
const container = setup();
|
|
54
54
|
const broken = () => { throw new Error("inner boom"); };
|
|
55
55
|
|
|
@@ -66,7 +66,7 @@ export default {
|
|
|
66
66
|
]
|
|
67
67
|
);
|
|
68
68
|
|
|
69
|
-
expect(container).toMatch(
|
|
69
|
+
await expect(container).toMatch(
|
|
70
70
|
[DIV,
|
|
71
71
|
[SECTION,
|
|
72
72
|
[ARTICLE, "inner fallback"]
|
|
@@ -75,7 +75,7 @@ export default {
|
|
|
75
75
|
);
|
|
76
76
|
},
|
|
77
77
|
|
|
78
|
-
"catch: nested error boundaries — outer catches when inner has no handler": () => {
|
|
78
|
+
"catch: nested error boundaries — outer catches when inner has no handler": async () => {
|
|
79
79
|
const container = setup();
|
|
80
80
|
const broken = () => { throw new Error("boom"); };
|
|
81
81
|
|
|
@@ -88,14 +88,14 @@ export default {
|
|
|
88
88
|
]
|
|
89
89
|
);
|
|
90
90
|
|
|
91
|
-
expect(container).toMatch(
|
|
91
|
+
await expect(container).toMatch(
|
|
92
92
|
[DIV,
|
|
93
93
|
[P, "outer caught it"]
|
|
94
94
|
]
|
|
95
95
|
);
|
|
96
96
|
},
|
|
97
97
|
|
|
98
|
-
"catch: error propagates when no handler exists on entire tree": () => {
|
|
98
|
+
"catch: error propagates when no handler exists on entire tree": async () => {
|
|
99
99
|
const container = setup();
|
|
100
100
|
const broken = () => { throw new Error("crash"); };
|
|
101
101
|
let threw = false;
|
|
@@ -108,10 +108,10 @@ export default {
|
|
|
108
108
|
threw = true;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
expect(threw).toEqual(true);
|
|
111
|
+
await expect(threw).toEqual(true);
|
|
112
112
|
},
|
|
113
113
|
|
|
114
|
-
"catch: catch handler changed on A→A path": () => {
|
|
114
|
+
"catch: catch handler changed on A→A path": async () => {
|
|
115
115
|
const container = setup();
|
|
116
116
|
const state = createState({ catchValue: "v1", showBroken: false });
|
|
117
117
|
const broken = () => { throw new Error("boom"); };
|
|
@@ -125,18 +125,18 @@ export default {
|
|
|
125
125
|
]
|
|
126
126
|
);
|
|
127
127
|
|
|
128
|
-
expect(container).toMatch(
|
|
128
|
+
await expect(container).toMatch(
|
|
129
129
|
[DIV, [SECTION, "ok"]]
|
|
130
130
|
);
|
|
131
131
|
|
|
132
132
|
patch({ catchValue: "v2", showBroken: true });
|
|
133
133
|
|
|
134
|
-
expect(container).toMatch(
|
|
134
|
+
await expect(container).toMatch(
|
|
135
135
|
[DIV, [P, "v2"]]
|
|
136
136
|
);
|
|
137
137
|
},
|
|
138
138
|
|
|
139
|
-
"catch: error in one sibling doesn't affect the other": () => {
|
|
139
|
+
"catch: error in one sibling doesn't affect the other": async () => {
|
|
140
140
|
const container = setup();
|
|
141
141
|
const broken = () => { throw new Error("boom"); };
|
|
142
142
|
|
|
@@ -150,7 +150,7 @@ export default {
|
|
|
150
150
|
]
|
|
151
151
|
);
|
|
152
152
|
|
|
153
|
-
expect(container).toMatch(
|
|
153
|
+
await expect(container).toMatch(
|
|
154
154
|
[DIV,
|
|
155
155
|
[P, "whoops"],
|
|
156
156
|
[ARTICLE, "i am fine"]
|