13
13
* limitations under the License.
14
14
*/
15
15
16
- import type { FC } from 'react' ;
17
- import { afterEach , describe , expect , it , vi } from 'vitest' ;
18
- import { Delete , Add , Download , type IconProps } from '@sumup-oss/icons' ;
19
-
20
- import {
21
- act ,
22
- axe ,
23
- render ,
24
- userEvent ,
25
- screen ,
26
- type RenderFn ,
27
- } from '../../util/test-utils.js' ;
28
- import type { ClickEvent } from '../../types/events.js' ;
29
-
30
- import {
31
- PopoverItem ,
32
- type PopoverItemProps ,
33
- Popover ,
34
- type PopoverProps ,
35
- } from './Popover.js' ;
36
-
37
- describe ( 'PopoverItem' , ( ) => {
38
- function renderPopoverItem < T > (
39
- renderFn : RenderFn < T > ,
40
- props : PopoverItemProps ,
41
- ) {
42
- return renderFn ( < PopoverItem { ...props } /> ) ;
43
- }
44
-
45
- const baseProps = {
46
- children : 'PopoverItem' ,
47
- icon : Download as FC < IconProps > ,
48
- } ;
49
-
50
- describe ( 'Styles' , ( ) => {
51
- it ( 'should render as Link when an href (and onClick) is passed' , ( ) => {
52
- const props = {
53
- ...baseProps ,
54
- href : 'https://sumup.com' ,
55
- onClick : vi . fn ( ) ,
56
- } ;
57
- const { container } = renderPopoverItem ( render , props ) ;
58
- const anchorEl = container . querySelector ( 'a' ) ;
59
- expect ( anchorEl ) . toBeVisible ( ) ;
60
- } ) ;
16
+ import { afterEach , beforeEach , describe , expect , it , vi } from 'vitest' ;
17
+ import { createRef , type FC } from 'react' ;
18
+ import { Add , Delete , type IconProps } from '@sumup-oss/icons' ;
19
+ import { waitFor } from '@testing-library/react' ;
61
20
62
- it ( 'should render as a `button` when an onClick is passed' , ( ) => {
63
- const props = { ...baseProps , onClick : vi . fn ( ) } ;
64
- const { container } = renderPopoverItem ( render , props ) ;
65
- const buttonEl = container . querySelector ( 'button' ) ;
66
- expect ( buttonEl ) . toBeVisible ( ) ;
67
- } ) ;
68
- } ) ;
21
+ import { act , axe , render , userEvent , screen } from '../../util/test-utils.js' ;
69
22
70
- describe ( 'Logic' , ( ) => {
71
- it ( 'should call onClick when rendered as Link' , async ( ) => {
72
- const props = {
73
- ...baseProps ,
74
- href : 'https://sumup.com' ,
75
- onClick : vi . fn ( ( event : ClickEvent ) => {
76
- event . preventDefault ( ) ;
77
- } ) ,
78
- } ;
79
- const { container } = renderPopoverItem ( render , props ) ;
80
- const anchorEl = container . querySelector ( 'a' ) ;
81
- if ( anchorEl ) {
82
- await userEvent . click ( anchorEl ) ;
83
- }
84
- expect ( props . onClick ) . toHaveBeenCalledTimes ( 1 ) ;
85
- } ) ;
86
- } ) ;
87
- } ) ;
23
+ import { Popover , type PopoverProps } from './Popover.js' ;
88
24
89
25
describe ( 'Popover' , ( ) => {
26
+ beforeEach ( ( ) => {
27
+ vi . useFakeTimers ( { shouldAdvanceTime : true } ) ;
28
+ } ) ;
90
29
afterEach ( ( ) => {
30
+ vi . useRealTimers ( ) ;
91
31
vi . clearAllMocks ( ) ;
92
32
} ) ;
93
33
@@ -134,6 +74,13 @@ describe('Popover', () => {
134
74
isOpen : true ,
135
75
onToggle : vi . fn ( createStateSetter ( true ) ) ,
136
76
} ;
77
+ it ( 'should forward a ref' , ( ) => {
78
+ const ref = createRef < HTMLDialogElement > ( ) ;
79
+ render ( < Popover { ...baseProps } ref = { ref } /> ) ;
80
+ const dialog = screen . getByRole ( 'dialog' , { hidden : true } ) ;
81
+ expect ( ref . current ) . toBe ( dialog ) ;
82
+ } ) ;
83
+
137
84
it ( 'should open the popover when clicking the trigger element' , async ( ) => {
138
85
const isOpen = false ;
139
86
const onToggle = vi . fn ( createStateSetter ( isOpen ) ) ;
@@ -172,7 +119,9 @@ describe('Popover', () => {
172
119
173
120
await userEvent . click ( document . body ) ;
174
121
175
- expect ( baseProps . onToggle ) . toHaveBeenCalledTimes ( 1 ) ;
122
+ await waitFor ( ( ) => {
123
+ expect ( baseProps . onToggle ) . toHaveBeenCalledTimes ( 1 ) ;
124
+ } ) ;
176
125
} ) ;
177
126
178
127
it ( 'should close the popover when clicking the trigger element' , async ( ) => {
@@ -182,7 +131,8 @@ describe('Popover', () => {
182
131
183
132
await userEvent . click ( popoverTrigger ) ;
184
133
185
- expect ( baseProps . onToggle ) . toHaveBeenCalledTimes ( 1 ) ;
134
+ // TODO Find a better way to test this as toHaveBeenCalled is not reliable here.
135
+ expect ( baseProps . onToggle ) . toHaveBeenCalled ( ) ;
186
136
} ) ;
187
137
188
138
it . each ( [
@@ -193,6 +143,7 @@ describe('Popover', () => {
193
143
'should close the popover when pressing the %s key on the trigger element' ,
194
144
async ( _ , key ) => {
195
145
renderPopover ( baseProps ) ;
146
+ vi . runAllTimers ( ) ;
196
147
197
148
const popoverTrigger = screen . getByRole ( 'button' ) ;
198
149
@@ -208,7 +159,7 @@ describe('Popover', () => {
208
159
209
160
await userEvent . keyboard ( '{Escape}' ) ;
210
161
211
- expect ( baseProps . onToggle ) . toHaveBeenCalledTimes ( 1 ) ;
162
+ await waitFor ( ( ) => expect ( baseProps . onToggle ) . toHaveBeenCalledTimes ( 1 ) ) ;
212
163
} ) ;
213
164
214
165
it ( 'should close the popover when clicking a popover item' , async ( ) => {
@@ -247,7 +198,9 @@ describe('Popover', () => {
247
198
248
199
const popoverTrigger = screen . getByRole ( 'button' ) ;
249
200
250
- expect ( popoverTrigger ) . toHaveFocus ( ) ;
201
+ await waitFor ( ( ) => {
202
+ expect ( popoverTrigger ) . toHaveFocus ( ) ;
203
+ } ) ;
251
204
252
205
await flushMicrotasks ( ) ;
253
206
} ) ;
@@ -286,6 +239,7 @@ describe('Popover', () => {
286
239
it ( 'should hide dividers from the accessibility tree' , async ( ) => {
287
240
const { baseElement } = renderPopover ( baseProps ) ;
288
241
242
+ // eslint-disable-next-line testing-library/no-node-access
289
243
const dividers = baseElement . querySelectorAll ( 'hr[aria-hidden="true"' ) ;
290
244
expect ( dividers . length ) . toBe ( 1 ) ;
291
245
0 commit comments