1
1
import {
2
+ configure as configureDTL ,
2
3
fireEvent as baseFireEvent ,
4
+ getConfig as getDTLConfig ,
3
5
getQueriesForElement ,
4
6
prettyDOM ,
5
7
} from '@testing-library/dom'
6
- import { tick } from 'svelte'
8
+ import * as Svelte from 'svelte'
7
9
8
10
import { mount , unmount , updateProps , validateOptions } from './core/index.js'
9
11
@@ -94,7 +96,7 @@ const render = (Component, options = {}, renderOptions = {}) => {
94
96
}
95
97
96
98
updateProps ( component , props )
97
- await tick ( )
99
+ await Svelte . tick ( )
98
100
} ,
99
101
unmount : ( ) => {
100
102
cleanupComponent ( component )
@@ -103,6 +105,33 @@ const render = (Component, options = {}, renderOptions = {}) => {
103
105
}
104
106
}
105
107
108
+ /** @type {import('@testing-library/dom'.Config | undefined } */
109
+ let originalDTLConfig
110
+
111
+ /**
112
+ * Configure `@testing-library/dom` for usage with Svelte.
113
+ *
114
+ * Ensures events fired from `@testing-library/dom`
115
+ * and `@testing-library/user-event` wait for Svelte
116
+ * to flush changes to the DOM before proceeding.
117
+ */
118
+ const setup = ( ) => {
119
+ originalDTLConfig = getDTLConfig ( )
120
+
121
+ configureDTL ( {
122
+ asyncWrapper : act ,
123
+ eventWrapper : Svelte . flushSync ?? ( ( cb ) => cb ( ) ) ,
124
+ } )
125
+ }
126
+
127
+ /** Reset dom-testing-library config. */
128
+ const cleanupDTL = ( ) => {
129
+ if ( originalDTLConfig ) {
130
+ configureDTL ( originalDTLConfig )
131
+ originalDTLConfig = undefined
132
+ }
133
+ }
134
+
106
135
/** Remove a component from the component cache. */
107
136
const cleanupComponent = ( component ) => {
108
137
const inCache = componentCache . delete ( component )
@@ -121,27 +150,31 @@ const cleanupTarget = (target) => {
121
150
}
122
151
}
123
152
124
- /** Unmount all components and remove elements added to `<body>`. */
153
+ /** Unmount components, remove elements added to `<body>`, and reset `@testing-library/dom `. */
125
154
const cleanup = ( ) => {
126
155
for ( const component of componentCache ) {
127
156
cleanupComponent ( component )
128
157
}
129
158
for ( const target of targetCache ) {
130
159
cleanupTarget ( target )
131
160
}
161
+ cleanupDTL ( )
132
162
}
133
163
134
164
/**
135
165
* Call a function and wait for Svelte to flush pending changes.
136
166
*
137
- * @param {() => unknown } [fn] - A function, which may be `async`, to call before flushing updates.
138
- * @returns {Promise<void> }
167
+ * @template T
168
+ * @param {(() => Promise<T>) | () => T } [fn] - A function, which may be `async`, to call before flushing updates.
169
+ * @returns {Promise<T> }
139
170
*/
140
171
const act = async ( fn ) => {
172
+ let result
141
173
if ( fn ) {
142
- await fn ( )
174
+ result = await fn ( )
143
175
}
144
- return tick ( )
176
+ await Svelte . tick ( )
177
+ return result
145
178
}
146
179
147
180
/**
@@ -162,18 +195,10 @@ const act = async (fn) => {
162
195
*
163
196
* @type {FireFunction & FireObject }
164
197
*/
165
- const fireEvent = async ( ...args ) => {
166
- const event = baseFireEvent ( ...args )
167
- await tick ( )
168
- return event
169
- }
198
+ const fireEvent = async ( ...args ) => act ( ( ) => baseFireEvent ( ...args ) )
170
199
171
200
for ( const [ key , baseEvent ] of Object . entries ( baseFireEvent ) ) {
172
- fireEvent [ key ] = async ( ...args ) => {
173
- const event = baseEvent ( ...args )
174
- await tick ( )
175
- return event
176
- }
201
+ fireEvent [ key ] = async ( ...args ) => act ( ( ) => baseEvent ( ...args ) )
177
202
}
178
203
179
- export { act , cleanup , fireEvent , render }
204
+ export { act , cleanup , fireEvent , render , setup }
0 commit comments