99 FireObject ,
1010 getQueriesForElement ,
1111 prettyDOM ,
12- waitFor ,
13- waitForElementToBeRemoved ,
12+ waitFor as dtlWaitFor ,
13+ waitForElementToBeRemoved as dtlWaitForElementToBeRemoved ,
1414 fireEvent as dtlFireEvent ,
1515 screen as dtlScreen ,
1616 queries as dtlQueries ,
@@ -153,38 +153,22 @@ export async function render<SutType, WrapperType = SutType>(
153153 container ?: HTMLElement ;
154154 timeout ?: number ;
155155 interval ?: number ;
156- mutationObserverOptions ?: {
157- subtree : boolean ;
158- childList : boolean ;
159- attributes : boolean ;
160- characterData : boolean ;
161- } ;
156+ mutationObserverOptions ?: MutationObserverInit ;
162157 } = { container : fixture . nativeElement } ,
163158 ) : Promise < T > {
164- return waitFor < T > ( ( ) => {
165- detectChanges ( ) ;
166- return callback ( ) ;
167- } , options ) ;
159+ return waitForWrapper ( detectChanges , callback , options ) ;
168160 }
169161
170162 function componentWaitForElementToBeRemoved < T > (
171- callback : ( ) => T ,
163+ callback : ( ( ) => T ) | T ,
172164 options : {
173165 container ?: HTMLElement ;
174166 timeout ?: number ;
175167 interval ?: number ;
176- mutationObserverOptions ?: {
177- subtree : boolean ;
178- childList : boolean ;
179- attributes : boolean ;
180- characterData : boolean ;
181- } ;
168+ mutationObserverOptions ?: MutationObserverInit ;
182169 } = { container : fixture . nativeElement } ,
183170 ) : Promise < T > {
184- return waitForElementToBeRemoved < T > ( ( ) => {
185- detectChanges ( ) ;
186- return callback ( ) ;
187- } , options ) ;
171+ return waitForElementToBeRemovedWrapper ( detectChanges , callback , options ) ;
188172 }
189173
190174 return {
@@ -266,28 +250,57 @@ function addAutoImports({ imports, routes }: Pick<RenderComponentOptions<any>, '
266250 return [ ...imports , ...animations ( ) , ...routing ( ) ] ;
267251}
268252
269- // for the findBy queries we first want to run a change detection cycle
270- function replaceFindWithFindAndDetectChanges < T > ( container : HTMLElement , originalQueriesForContainer : T ) : T {
271- return Object . keys ( originalQueriesForContainer ) . reduce (
272- ( newQueries , key ) => {
273- if ( key . startsWith ( 'find' ) ) {
274- const getByQuery = dtlQueries [ key . replace ( 'find' , 'get' ) ] ;
275- newQueries [ key ] = async ( text , options , waitForOptions ) => {
276- // original implementation at https://github.com/testing-library/dom-testing-library/blob/master/src/query-helpers.js
277- const result = await waitFor ( ( ) => {
278- detectChangesForMountedFixtures ( ) ;
279- return getByQuery ( container , text , options ) ;
280- } , waitForOptions ) ;
281- return result ;
282- } ;
283- } else {
284- newQueries [ key ] = originalQueriesForContainer [ key ] ;
253+ /**
254+ * Wrap waitFor to poke the Angular change detection cycle before invoking the callback
255+ */
256+ async function waitForWrapper < T > (
257+ detectChanges : ( ) => void ,
258+ callback : ( ) => T ,
259+ options ?: {
260+ container ?: HTMLElement ;
261+ timeout ?: number ;
262+ interval ?: number ;
263+ mutationObserverOptions ?: MutationObserverInit ;
264+ } ,
265+ ) : Promise < T > {
266+ return await dtlWaitFor ( ( ) => {
267+ detectChanges ( ) ;
268+ return callback ( ) ;
269+ } , options ) ;
270+ }
271+
272+ /**
273+ * Wrap waitForElementToBeRemovedWrapper to poke the Angular change detection cycle before invoking the callback
274+ */
275+ async function waitForElementToBeRemovedWrapper < T > (
276+ detectChanges : ( ) => void ,
277+ callback : ( ( ) => T ) | T ,
278+ options ?: {
279+ container ?: HTMLElement ;
280+ timeout ?: number ;
281+ interval ?: number ;
282+ mutationObserverOptions ?: MutationObserverInit ;
283+ } ,
284+ ) : Promise < T > {
285+ let cb ;
286+ if ( typeof callback !== 'function' ) {
287+ const elements = ( Array . isArray ( callback ) ? callback : [ callback ] ) as HTMLElement [ ] ;
288+ const getRemainingElements = elements . map ( element => {
289+ let parent = element . parentElement ;
290+ while ( parent . parentElement ) {
291+ parent = parent . parentElement ;
285292 }
293+ return ( ) => ( parent . contains ( element ) ? element : null ) ;
294+ } ) ;
295+ cb = ( ) => getRemainingElements . map ( c => c ( ) ) . filter ( Boolean ) ;
296+ } else {
297+ cb = callback ;
298+ }
286299
287- return newQueries ;
288- } ,
289- { } as T ,
290- ) ;
300+ return await dtlWaitForElementToBeRemoved ( ( ) => {
301+ detectChanges ( ) ;
302+ return cb ( ) ;
303+ } , options ) ;
291304}
292305
293306function cleanup ( ) {
@@ -307,11 +320,43 @@ if (typeof afterEach === 'function' && !process.env.ATL_SKIP_AUTO_CLEANUP) {
307320 } ) ;
308321}
309322
323+ /**
324+ * Wrap findBy queries to poke the Angular change detection cycle
325+ */
326+ function replaceFindWithFindAndDetectChanges < T > ( container : HTMLElement , originalQueriesForContainer : T ) : T {
327+ return Object . keys ( originalQueriesForContainer ) . reduce (
328+ ( newQueries , key ) => {
329+ if ( key . startsWith ( 'find' ) ) {
330+ const getByQuery = dtlQueries [ key . replace ( 'find' , 'get' ) ] ;
331+ newQueries [ key ] = async ( text , options , waitForOptions ) => {
332+ // original implementation at https://github.com/testing-library/dom-testing-library/blob/master/src/query-helpers.js
333+ const result = await waitForWrapper (
334+ detectChangesForMountedFixtures ,
335+ ( ) => getByQuery ( container , text , options ) ,
336+ waitForOptions ,
337+ ) ;
338+ return result ;
339+ } ;
340+ } else {
341+ newQueries [ key ] = originalQueriesForContainer [ key ] ;
342+ }
343+
344+ return newQueries ;
345+ } ,
346+ { } as T ,
347+ ) ;
348+ }
349+
350+ /**
351+ * Call detectChanges for all fixtures
352+ */
310353function detectChangesForMountedFixtures ( ) {
311354 mountedFixtures . forEach ( fixture => fixture . detectChanges ( ) ) ;
312355}
313356
314- // wrap dom-fireEvent with a change detection cycle
357+ /**
358+ * Wrap dom-fireEvent to poke the Angular change detection cycle after an event is fired
359+ */
315360const fireEvent = Object . keys ( dtlFireEvent ) . reduce (
316361 ( events , key ) => {
317362 events [ key ] = ( element : HTMLElement , options ?: { } ) => {
@@ -324,18 +369,55 @@ const fireEvent = Object.keys(dtlFireEvent).reduce(
324369 { } as typeof dtlFireEvent ,
325370) ;
326371
372+ /**
373+ * Re-export screen with patched queries
374+ */
327375const screen = replaceFindWithFindAndDetectChanges ( document . body , dtlScreen ) ;
328376
329- // wrap user-events with the correct fireEvents
377+ /**
378+ * Re-export waitFor with patched waitFor
379+ */
380+ async function waitFor < T > (
381+ callback : ( ) => T ,
382+ options ?: {
383+ container ?: HTMLElement ;
384+ timeout ?: number ;
385+ interval ?: number ;
386+ mutationObserverOptions ?: MutationObserverInit ;
387+ } ,
388+ ) : Promise < T > {
389+ return waitForWrapper ( detectChangesForMountedFixtures , callback , options ) ;
390+ }
391+
392+ /**
393+ * Re-export waitForElementToBeRemoved with patched waitForElementToBeRemoved
394+ */
395+ async function waitForElementToBeRemoved < T > (
396+ callback : ( ( ) => T ) | T ,
397+ options ?: {
398+ container ?: HTMLElement ;
399+ timeout ?: number ;
400+ interval ?: number ;
401+ mutationObserverOptions ?: MutationObserverInit ;
402+ } ,
403+ ) : Promise < T > {
404+ return waitForElementToBeRemovedWrapper ( detectChangesForMountedFixtures , callback , options ) ;
405+ }
406+
407+ /**
408+ * Re-export userEvent with the patched fireEvent
409+ */
330410const userEvent = {
331411 type : createType ( fireEvent ) ,
332412 selectOptions : createSelectOptions ( fireEvent ) ,
333413 tab : tab ,
334414} ;
335415
336- // manually export otherwise we get the following error while running Jest tests
337- // TypeError: Cannot set property fireEvent of [object Object] which has only a getter
338- // exports.fireEvent = fireEvent;
416+ /**
417+ * Manually export otherwise we get the following error while running Jest tests
418+ * TypeError: Cannot set property fireEvent of [object Object] which has only a getter
419+ * exports.fireEvent = fireEvent
420+ */
339421export {
340422 buildQueries ,
341423 configure ,
@@ -401,12 +483,7 @@ export {
401483 queryAllByAttribute ,
402484 queryByAttribute ,
403485 queryHelpers ,
404- wait ,
405- waitFor ,
406- waitForDomChange ,
407- waitForElement ,
408- waitForElementToBeRemoved ,
409486 within ,
410487} from '@testing-library/dom' ;
411488
412- export { fireEvent , screen , userEvent } ;
489+ export { fireEvent , screen , userEvent , waitFor , waitForElementToBeRemoved } ;
0 commit comments