-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathpure.js
131 lines (106 loc) · 3.28 KB
/
pure.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import {
fireEvent as dtlFireEvent,
getQueriesForElement,
prettyDOM,
} from '@testing-library/dom'
import { tick, createRoot } from 'svelte'
const containerCache = new Set()
const componentCache = new Set()
const svelteComponentOptions = [
'accessors',
'anchor',
'props',
'hydrate',
'intro',
'context',
]
const render = (
Component,
{ target, ...options } = {},
{ container, queries } = {},
) => {
container = container || document.body
target = target || container.appendChild(document.createElement('div'))
const ComponentConstructor = Component.default || Component
const checkProps = (options) => {
const isProps = !Object.keys(options).some((option) =>
svelteComponentOptions.includes(option),
)
// Check if any props and Svelte options were accidentally mixed.
if (!isProps) {
const unrecognizedOptions = Object.keys(options).filter(
(option) => !svelteComponentOptions.includes(option),
)
if (unrecognizedOptions.length > 0) {
throw Error(`
Unknown options were found [${unrecognizedOptions}]. This might happen if you've mixed
passing in props with Svelte options into the render function. Valid Svelte options
are [${svelteComponentOptions}]. You can either change the prop names, or pass in your
props for that component via the \`props\` option.\n\n
Eg: const { /** Results **/ } = render(MyComponent, { props: { /** props here **/ } })\n\n
`)
}
return options
}
return { props: options }
}
let component = createRoot(ComponentConstructor, {
target,
...checkProps(options),
ondestroy: () => componentCache.delete(component),
})
containerCache.add({ container, target, component })
componentCache.add(component)
return {
container,
component,
debug: (el = container) => console.log(prettyDOM(el)),
rerender: (options) => {
if (componentCache.has(component)) component.$destroy()
component = createRoot(ComponentConstructor, {
target,
...checkProps(options),
ondestroy: () => componentCache.delete(component),
})
containerCache.add({ container, target, component })
componentCache.add(component)
},
unmount: () => {
if (componentCache.has(component)) component.$destroy()
},
...getQueriesForElement(container, queries),
}
}
const cleanupAtContainer = (cached) => {
const { target, component } = cached
if (componentCache.has(component)) component.$destroy()
if (target.parentNode === document.body) {
document.body.removeChild(target)
}
containerCache.delete(cached)
}
const cleanup = () => {
Array.from(containerCache.keys()).forEach(cleanupAtContainer)
}
const act = (fn) => {
const value = fn && fn()
if (value !== undefined && typeof value.then === 'function') {
return value.then(() => tick())
}
return tick()
}
const fireEvent = async (...args) => {
const event = dtlFireEvent(...args)
await tick()
return event
}
Object.keys(dtlFireEvent).forEach((key) => {
fireEvent[key] = async (...args) => {
const event = dtlFireEvent[key](...args)
await tick()
return event
}
})
/* eslint-disable import/export */
export * from '@testing-library/dom'
export { render, cleanup, fireEvent, act }