1- import { render , screen } from '@testing-library/react'
2- import { describe , expect , it } from 'vitest'
1+ import { act , cleanup , render , screen } from '@testing-library/react'
2+ import { afterEach , describe , expect , it , vi } from 'vitest'
33
44import { Spin } from './Spin'
55
6+ afterEach ( ( ) => {
7+ cleanup ( )
8+ vi . useRealTimers ( )
9+ } )
10+
611describe ( 'Spin' , ( ) => {
712 it ( 'announces standalone loading state as a polite status' , ( ) => {
813 render ( < Spin /> )
@@ -20,6 +25,38 @@ describe('Spin', () => {
2025 expect ( screen . getByText ( 'Loading invoices' ) ) . toBeInTheDocument ( )
2126 } )
2227
28+ it ( 'delays the standalone loading status when delay is set' , ( ) => {
29+ vi . useFakeTimers ( )
30+
31+ render ( < Spin delay = { 200 } /> )
32+
33+ expect ( screen . queryByRole ( 'status' ) ) . not . toBeInTheDocument ( )
34+
35+ act ( ( ) => {
36+ vi . advanceTimersByTime ( 199 )
37+ } )
38+ expect ( screen . queryByRole ( 'status' ) ) . not . toBeInTheDocument ( )
39+
40+ act ( ( ) => {
41+ vi . advanceTimersByTime ( 1 )
42+ } )
43+ expect ( screen . getByRole ( 'status' , { name : 'Loading' } ) ) . toBeInTheDocument ( )
44+ } )
45+
46+ it ( 'does not show a delayed spinner when spinning stops before delay ends' , ( ) => {
47+ vi . useFakeTimers ( )
48+
49+ const { rerender } = render ( < Spin delay = { 200 } /> )
50+
51+ rerender ( < Spin spinning = { false } delay = { 200 } /> )
52+
53+ act ( ( ) => {
54+ vi . advanceTimersByTime ( 200 )
55+ } )
56+
57+ expect ( screen . queryByRole ( 'status' ) ) . not . toBeInTheDocument ( )
58+ } )
59+
2360 it ( 'marks wrapped content busy while the overlay is spinning' , ( ) => {
2461 render (
2562 < Spin spinning tip = "Refreshing data" >
@@ -33,6 +70,26 @@ describe('Spin', () => {
3370 expect ( screen . getByRole ( 'status' , { name : 'Refreshing data' } ) ) . toBeInTheDocument ( )
3471 } )
3572
73+ it ( 'marks wrapped content busy while a delayed overlay is pending' , ( ) => {
74+ vi . useFakeTimers ( )
75+
76+ render (
77+ < Spin spinning delay = { 200 } tip = "Refreshing data" >
78+ < section aria-label = "Report panel" > Report content</ section >
79+ </ Spin > ,
80+ )
81+
82+ const wrapper = screen . getByText ( 'Report content' ) . parentElement
83+
84+ expect ( wrapper ) . toHaveAttribute ( 'aria-busy' , 'true' )
85+ expect ( screen . queryByRole ( 'status' ) ) . not . toBeInTheDocument ( )
86+
87+ act ( ( ) => {
88+ vi . advanceTimersByTime ( 200 )
89+ } )
90+ expect ( screen . getByRole ( 'status' , { name : 'Refreshing data' } ) ) . toBeInTheDocument ( )
91+ } )
92+
3693 it ( 'marks wrapped content not busy and hides status when spinning stops' , ( ) => {
3794 render (
3895 < Spin spinning = { false } >
@@ -45,4 +102,4 @@ describe('Spin', () => {
45102 expect ( wrapper ) . toHaveAttribute ( 'aria-busy' , 'false' )
46103 expect ( screen . queryByRole ( 'status' ) ) . not . toBeInTheDocument ( )
47104 } )
48- } )
105+ } )
0 commit comments