forked from hyperdivision/vhs-tape
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
110 lines (95 loc) · 3.47 KB
/
index.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
104
105
106
107
108
109
110
const tape = require('tape')
const onload = require('fast-on-load')
const createElement = document.createElement.bind(document)
const testBody = createElement('div')
testBody.id = 'vhs-test-body'
document.body.appendChild(testBody)
function create (delay, fn) {
if (!delay) delay = Number(process.env.VHS_DELAY) || 0
function queueTest (description, testFn) {
const tpe = fn ? tape[fn].bind(tape) : tape
tpe(description, t => {
const testElementGroup = createElement('div')
const descriptionEl = createElement('div')
descriptionEl.innerText = description
testElementGroup.appendChild(descriptionEl)
const testElement = createElement('div')
testElement.classList.add('test-element')
testElementGroup.appendChild(testElement)
testBody.appendChild(testElementGroup)
const maybePromise = testFn(createTestHarness(t, testElement))
if (maybePromise && maybePromise.then) {
maybePromise.then(t.end).catch(t.end)
}
})
}
queueTest.delay = function (ms) {
return create(ms)
}
queueTest.skip = function (description, testFn) {
return create(0, 'skip')(description, testFn)
}
queueTest.slow = function (description, testFn) {
return create(500)(description, testFn)
}
queueTest.only = function (description, testFn) {
return create(0, 'only')(description, testFn)
}
return queueTest
function createTestHarness (t, element) {
return Object.assign(t, {
element,
sleep: ms => new Promise((resolve) => setTimeout(resolve, ms)),
onload: node => new Promise(resolve => {
const resolveFn = () => {
onload.delete(node, resolveFn)
t.delay().then(resolve)
}
node.isConnected ? resolveFn() : onload(node, resolveFn)
}),
unload: node => new Promise(resolve => {
const resolveFn = () => {
onload.delete(node, undefined, resolveFn)
t.delay().then(resolve)
}
!node.isConnected ? resolveFn() : onload(node, undefined, resolveFn)
}),
raf: () => new Promise(resolve => window.requestAnimationFrame(() => resolve())),
delay () {
return delay ? t.sleep(delay) : t.raf()
},
click (stringOrElement) {
toElement(stringOrElement).click()
return t.delay()
},
focus (stringOrElement) {
toElement(stringOrElement).focus()
return t.delay()
},
async type (str, event) {
for (const c of str.split('')) {
const el = document.activeElement
const keyData = {
key: c,
code: c.charCodeAt(0).toString(),
charCode: c.charCodeAt(0),
keyCode: c.charCodeAt(0)
}
if (!el) throw new Error('typing with no focused element')
await t.delay()
el.dispatchEvent(new window.KeyboardEvent('keydown', keyData))
el.dispatchEvent(new window.KeyboardEvent('keypress', keyData))
el.value = el.value + c
el.dispatchEvent(new window.KeyboardEvent('keyup', keyData))
}
return t.delay()
}
})
function toElement (stringOrElement) {
if (typeof stringOrElement === 'string') stringOrElement = element.querySelector(stringOrElement)
if (!(stringOrElement instanceof window.HTMLElement)) throw new Error('stringOrElement needs to be an instance of HTMLElement or a querySelector that resolves to a HTMLElement')
return stringOrElement
}
}
}
module.exports = create(0)