-
-
Notifications
You must be signed in to change notification settings - Fork 43
/
test-dom.js
103 lines (90 loc) · 2.5 KB
/
test-dom.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { h, render, Mark } from "./src/core.js";
import { isArray } from "./src/utils.js";
/**
* @type {Object<string,{ref: HTMLDivElement, id: number, mount?: boolean}>}
*/
const TEST_HOST = {};
let TEST_KEY = 0;
const fill = (vnode) =>
vnode && vnode.type == "host" ? vnode : h("host", null, vnode);
if (window.beforeEach) {
window.beforeEach(() => {
const id = ++TEST_KEY;
const host = document.createElement("div");
host.id = "fixture-" + id;
TEST_HOST[id] = {
id,
host,
};
});
if (window.afterEach) {
window.afterEach(() => {
const { host } = TEST_HOST[TEST_KEY];
host.remove();
});
}
}
/**
*
* @param {Element} node
* @param {string|symbol} [id]
* @returns
*/
export const getFragment = (node, id) => {
const children = [];
if (id) {
if (node[id].fragment) {
let { markStart, markEnd } = node[id].fragment;
while ((markStart = markStart.nextSibling) != markEnd)
children.push(markStart);
}
} else {
let markStart = node.firstChild;
while (markStart) {
if (!(markStart instanceof Mark)) children.push(markStart);
markStart = markStart.nextSibling;
}
}
return children;
};
/**
*
* @param {any} Vnode
* @returns {HTMLDivElement}
*/
export function fixture(vnode) {
const ref = TEST_HOST[TEST_KEY];
if (!ref)
throw "fixture depends on the global functions beforeEach and afterEach";
const nextVnode = fill(vnode);
const id = "fixture:" + ref.id;
render(nextVnode, ref.host, id);
// insert the content into the document
if (!ref.mount) {
ref.mount = true;
document.body.appendChild(ref.host);
}
const children = getFragment(ref.host, id);
return nextVnode == vnode
? ref.host
: isArray(vnode)
? children
: children[0];
}
/**
* @param {ChildNode | typeof window } node
* @param {string} type
* @param {boolean | AddEventListenerOptions} [options]
* @returns {Promise<Event>}
*/
export const asyncEventListener = (node, type, options) =>
new Promise((resolve) => node.addEventListener(type, resolve, options));
/**
* @type {import("./types/test-dom").DispatchEvent}
*/
export const dispatchEvent = (currentTarget, event, target) => {
if (target != null) {
Object.defineProperty(event, "target", { value: target });
}
return currentTarget.dispatchEvent(event);
};