Skip to content

Commit d55fbd7

Browse files
committed
alias pure.js to svelte5.js
1 parent 44b20b4 commit d55fbd7

File tree

3 files changed

+158
-4
lines changed

3 files changed

+158
-4
lines changed

src/pure.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import {
44
prettyDOM,
55
} from '@testing-library/dom'
66
import { VERSION as SVELTE_VERSION } from 'svelte/compiler'
7-
import { createClassComponent as createComponentSvelte5 } from 'svelte/legacy'
87
import * as Svelte from 'svelte'
98

109
const IS_SVELTE_5 = /^5\./.test(SVELTE_VERSION)
1110
const targetCache = new Set()
1211
const componentCache = new Set()
1312

13+
if (IS_SVELTE_5)
14+
console.warn('for Svelte 5, use `@testing-library/svelte/svelte5`')
15+
1416
const svelteComponentOptions = IS_SVELTE_5
1517
? ['target', 'props', 'events', 'context', 'intro', 'recover']
1618
: ['accessors', 'anchor', 'props', 'hydrate', 'intro', 'context']
@@ -56,9 +58,10 @@ const render = (
5658
const renderComponent = (options) => {
5759
options = { target, ...checkProps(options) }
5860

59-
const component = IS_SVELTE_5
60-
? createComponentSvelte5({ component: ComponentConstructor, ...options })
61-
: new ComponentConstructor(options)
61+
if (IS_SVELTE_5)
62+
throw new Error('for Svelte 5, use `@testing-library/svelte/svelte5`')
63+
64+
const component = new ComponentConstructor(options)
6265

6366
componentCache.add(component)
6467

src/svelte5.js

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import {
2+
fireEvent as dtlFireEvent,
3+
getQueriesForElement,
4+
prettyDOM,
5+
} from '@testing-library/dom'
6+
import { VERSION as SVELTE_VERSION } from 'svelte/compiler'
7+
import { createClassComponent as createComponentSvelte5 } from 'svelte/legacy'
8+
import * as Svelte from 'svelte'
9+
10+
const IS_SVELTE_5 = /^5\./.test(SVELTE_VERSION)
11+
const targetCache = new Set()
12+
const componentCache = new Set()
13+
14+
const svelteComponentOptions = IS_SVELTE_5
15+
? ['target', 'props', 'events', 'context', 'intro', 'recover']
16+
: ['accessors', 'anchor', 'props', 'hydrate', 'intro', 'context']
17+
18+
const render = (
19+
Component,
20+
{ target, ...options } = {},
21+
{ container, queries } = {}
22+
) => {
23+
container = container || document.body
24+
target = target || container.appendChild(document.createElement('div'))
25+
targetCache.add(target)
26+
27+
const ComponentConstructor = Component.default || Component
28+
29+
const checkProps = (options) => {
30+
const isProps = !Object.keys(options).some((option) =>
31+
svelteComponentOptions.includes(option)
32+
)
33+
34+
// Check if any props and Svelte options were accidentally mixed.
35+
if (!isProps) {
36+
const unrecognizedOptions = Object.keys(options).filter(
37+
(option) => !svelteComponentOptions.includes(option)
38+
)
39+
40+
if (unrecognizedOptions.length > 0) {
41+
throw Error(`
42+
Unknown options were found [${unrecognizedOptions}]. This might happen if you've mixed
43+
passing in props with Svelte options into the render function. Valid Svelte options
44+
are [${svelteComponentOptions}]. You can either change the prop names, or pass in your
45+
props for that component via the \`props\` option.\n\n
46+
Eg: const { /** Results **/ } = render(MyComponent, { props: { /** props here **/ } })\n\n
47+
`)
48+
}
49+
50+
return options
51+
}
52+
53+
return { props: options }
54+
}
55+
56+
const renderComponent = (options) => {
57+
options = { target, ...checkProps(options) }
58+
59+
const component = IS_SVELTE_5
60+
? createComponentSvelte5({ component: ComponentConstructor, ...options })
61+
: new ComponentConstructor(options)
62+
63+
componentCache.add(component)
64+
65+
// TODO(mcous, 2024-02-11): remove this behavior in the next major version
66+
// It is unnecessary has no path to implementation in Svelte v5
67+
if (!IS_SVELTE_5) {
68+
component.$$.on_destroy.push(() => {
69+
componentCache.delete(component)
70+
})
71+
}
72+
73+
return component
74+
}
75+
76+
let component = renderComponent(options)
77+
78+
return {
79+
container,
80+
component,
81+
debug: (el = container) => console.log(prettyDOM(el)),
82+
rerender: async (props) => {
83+
if (props.props) {
84+
console.warn(
85+
'rerender({ props: {...} }) deprecated, use rerender({...}) instead'
86+
)
87+
props = props.props
88+
}
89+
component.$set(props)
90+
await Svelte.tick()
91+
},
92+
unmount: () => {
93+
cleanupComponent(component)
94+
},
95+
...getQueriesForElement(container, queries),
96+
}
97+
}
98+
99+
const cleanupComponent = (component) => {
100+
const inCache = componentCache.delete(component)
101+
102+
if (inCache) {
103+
component.$destroy()
104+
}
105+
}
106+
107+
const cleanupTarget = (target) => {
108+
const inCache = targetCache.delete(target)
109+
110+
if (inCache && target.parentNode === document.body) {
111+
document.body.removeChild(target)
112+
}
113+
}
114+
115+
const cleanup = () => {
116+
componentCache.forEach(cleanupComponent)
117+
targetCache.forEach(cleanupTarget)
118+
}
119+
120+
const act = async (fn) => {
121+
if (fn) {
122+
await fn()
123+
}
124+
return Svelte.tick()
125+
}
126+
127+
const fireEvent = async (...args) => {
128+
const event = dtlFireEvent(...args)
129+
await Svelte.tick()
130+
return event
131+
}
132+
133+
Object.keys(dtlFireEvent).forEach((key) => {
134+
fireEvent[key] = async (...args) => {
135+
const event = dtlFireEvent[key](...args)
136+
await Svelte.tick()
137+
return event
138+
}
139+
})
140+
141+
/* eslint-disable import/export */
142+
143+
export * from '@testing-library/dom'
144+
145+
export { render, cleanup, fireEvent, act }

vite.config.js

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { svelte } from '@sveltejs/vite-plugin-svelte'
22
import { defineConfig } from 'vite'
3+
import { VERSION as SVELTE_VERSION } from 'svelte/compiler'
4+
5+
const alias = {}
6+
7+
if (SVELTE_VERSION >= '5') alias['./pure.js'] = './svelte5.js'
38

49
// https://vitejs.dev/config/
510
export default defineConfig(({ mode }) => ({
@@ -20,5 +25,6 @@ export default defineConfig(({ mode }) => ({
2025
provider: 'v8',
2126
include: ['src'],
2227
},
28+
alias,
2329
},
2430
}))

0 commit comments

Comments
 (0)