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