@@ -3,6 +3,7 @@ import React from 'react';
3
3
import ReactDOM from 'react-dom' ;
4
4
import { act } from 'react-dom/test-utils' ;
5
5
import simulant from 'simulant' ;
6
+ import { activeElement } from 'dom-helpers' ;
6
7
import Dropdown from '../src/Dropdown' ;
7
8
8
9
describe ( '<Dropdown>' , ( ) => {
@@ -15,20 +16,21 @@ describe('<Dropdown>', () => {
15
16
} ) => (
16
17
< Dropdown . Menu
17
18
flip
18
- popperConfig = { popperConfig }
19
19
usePopper = { usePopper }
20
+ popperConfig = { popperConfig }
20
21
rootCloseEvent = { rootCloseEvent }
21
22
>
22
- { ( args ) => {
23
- renderSpy && renderSpy ( args ) ;
24
- const { show, close, props : menuProps } = args ;
23
+ { ( menuProps , meta ) => {
24
+ const { show, toggle } = meta ;
25
+ renderSpy && renderSpy ( meta ) ;
26
+
25
27
return (
26
28
< div
27
29
{ ...props }
28
30
{ ...menuProps }
29
31
data-show = { show }
30
32
className = "menu"
31
- onClick = { close }
33
+ onClick = { ( ) => toggle ( false ) }
32
34
style = { { display : show ? 'flex' : 'none' } }
33
35
/>
34
36
) ;
@@ -38,39 +40,46 @@ describe('<Dropdown>', () => {
38
40
39
41
const Toggle = ( props ) => (
40
42
< Dropdown . Toggle >
41
- { ( { toggle , props : toggleProps } ) => (
43
+ { ( toggleProps ) => (
42
44
< button
43
45
{ ...props }
44
46
{ ...toggleProps }
45
47
id = "test-id"
46
48
type = "button"
47
49
className = "toggle"
48
- onClick = { toggle }
49
50
/>
50
51
) }
51
52
</ Dropdown . Toggle >
52
53
) ;
53
54
54
55
const SimpleDropdown = ( { children, menuSpy, usePopper, ...outer } ) => (
55
56
< Dropdown { ...outer } >
56
- { ( { props } ) => (
57
- < div tabIndex = "-1" { ...props } >
58
- { children || (
59
- < >
60
- < Toggle key = "toggle" > Child Title</ Toggle > ,
61
- < Menu key = "menu" renderSpy = { menuSpy } usePopper = { usePopper } >
62
- < button type = "button" > Item 1</ button >
63
- < button type = "button" > Item 2</ button >
64
- < button type = "button" > Item 3</ button >
65
- < button type = "button" > Item 4</ button >
66
- </ Menu >
67
- </ >
68
- ) }
69
- </ div >
57
+ { children || (
58
+ < >
59
+ < Toggle key = "toggle" > Child Title</ Toggle > ,
60
+ < Menu key = "menu" renderSpy = { menuSpy } usePopper = { usePopper } >
61
+ < button type = "button" > Item 1</ button >
62
+ < button type = "button" > Item 2</ button >
63
+ < button type = "button" > Item 3</ button >
64
+ < button type = "button" > Item 4</ button >
65
+ </ Menu >
66
+ </ >
70
67
) }
71
68
</ Dropdown >
72
69
) ;
73
70
71
+ let focusableContainer ;
72
+
73
+ beforeEach ( ( ) => {
74
+ focusableContainer = document . createElement ( 'div' ) ;
75
+ document . body . appendChild ( focusableContainer ) ;
76
+ } ) ;
77
+
78
+ afterEach ( ( ) => {
79
+ ReactDOM . unmountComponentAtNode ( focusableContainer ) ;
80
+ document . body . removeChild ( focusableContainer ) ;
81
+ } ) ;
82
+
74
83
it ( 'renders toggle with Dropdown.Toggle' , ( ) => {
75
84
const buttonNode = mount ( < SimpleDropdown /> )
76
85
. assertSingle ( 'button.toggle' )
@@ -84,8 +93,8 @@ describe('<Dropdown>', () => {
84
93
} ) ;
85
94
86
95
it ( 'forwards alignEnd to menu' , ( ) => {
87
- const renderSpy = sinon . spy ( ( args ) => {
88
- args . alignEnd . should . equal ( true ) ;
96
+ const renderSpy = sinon . spy ( ( meta ) => {
97
+ meta . alignEnd . should . equal ( true ) ;
89
98
} ) ;
90
99
91
100
mount (
@@ -108,6 +117,7 @@ describe('<Dropdown>', () => {
108
117
wrapper . assertSingle ( 'ReactOverlaysDropdown' ) ;
109
118
110
119
wrapper . assertSingle ( 'div[data-show=true]' ) ;
120
+
111
121
wrapper . assertSingle ( 'button[aria-expanded=true]' ) . simulate ( 'click' ) ;
112
122
113
123
wrapper . assertNone ( '.show' ) ;
@@ -135,15 +145,13 @@ describe('<Dropdown>', () => {
135
145
136
146
const wrapper = mount (
137
147
< Dropdown onToggle = { closeSpy } id = "test-id" >
138
- { ( ) => (
139
- < div >
140
- < Toggle > Child Title</ Toggle > ,
141
- < Menu rootCloseEvent = "mousedown" >
142
- < button type = "button" > Item 1</ button >
143
- < button type = "button" > Item 2</ button >
144
- </ Menu >
145
- </ div >
146
- ) }
148
+ < div >
149
+ < Toggle > Child Title</ Toggle > ,
150
+ < Menu rootCloseEvent = "mousedown" >
151
+ < button type = "button" > Item 1</ button >
152
+ < button type = "button" > Item 2</ button >
153
+ </ Menu >
154
+ </ div >
147
155
</ Dropdown > ,
148
156
) ;
149
157
@@ -160,11 +168,13 @@ describe('<Dropdown>', () => {
160
168
} ) ;
161
169
162
170
it ( 'when focused and closed toggles open when the key "down" is pressed' , ( ) => {
163
- const wrapper = mount ( < SimpleDropdown /> ) ;
171
+ const wrapper = mount ( < SimpleDropdown /> , { attachTo : focusableContainer } ) ;
164
172
165
- wrapper . find ( '.toggle' ) . simulate ( 'keyDown' , { key : 'ArrowDown' } ) ;
173
+ simulant . fire ( wrapper . find ( '.toggle' ) . getDOMNode ( ) , 'keydown' , {
174
+ key : 'ArrowDown' ,
175
+ } ) ;
166
176
167
- wrapper . assertSingle ( 'ReactOverlaysDropdownMenu div' ) ;
177
+ wrapper . update ( ) . assertSingle ( 'ReactOverlaysDropdownMenu div' ) ;
168
178
} ) ;
169
179
170
180
it ( 'closes when item is clicked' , ( ) => {
@@ -207,29 +217,15 @@ describe('<Dropdown>', () => {
207
217
} ) ;
208
218
209
219
describe ( 'focusable state' , ( ) => {
210
- let focusableContainer ;
211
-
212
- beforeEach ( ( ) => {
213
- focusableContainer = document . createElement ( 'div' ) ;
214
- document . body . appendChild ( focusableContainer ) ;
215
- } ) ;
216
-
217
- afterEach ( ( ) => {
218
- ReactDOM . unmountComponentAtNode ( focusableContainer ) ;
219
- document . body . removeChild ( focusableContainer ) ;
220
- } ) ;
221
-
222
220
it ( 'when focus should not be moved to first item when focusFirstItemOnShow is `false`' , ( ) => {
223
221
const wrapper = mount (
224
222
< Dropdown focusFirstItemOnShow = { false } >
225
- { ( { props } ) => (
226
- < div { ...props } >
227
- < Toggle > Child Title</ Toggle > ,
228
- < Menu >
229
- < button type = "button" > Item 1</ button >
230
- </ Menu >
231
- </ div >
232
- ) }
223
+ < div >
224
+ < Toggle > Child Title</ Toggle > ,
225
+ < Menu >
226
+ < button type = "button" > Item 1</ button >
227
+ </ Menu >
228
+ </ div >
233
229
</ Dropdown > ,
234
230
{ attachTo : focusableContainer } ,
235
231
) ;
@@ -244,40 +240,39 @@ describe('<Dropdown>', () => {
244
240
it ( 'when focused and closed sets focus on first menu item when the key "down" is pressed for role="menu"' , ( ) => {
245
241
const wrapper = mount (
246
242
< Dropdown >
247
- { ( { props } ) => (
248
- < div { ...props } >
249
- < Toggle > Child Title</ Toggle > ,
250
- < Menu role = "menu" >
251
- < button type = "button" > Item 1</ button >
252
- < button type = "button" > Item 2</ button >
253
- </ Menu >
254
- </ div >
255
- ) }
243
+ < div >
244
+ < Toggle > Child Title</ Toggle > ,
245
+ < Menu role = "menu" >
246
+ < button type = "button" > Item 1</ button >
247
+ < button type = "button" > Item 2</ button >
248
+ </ Menu >
249
+ </ div >
256
250
</ Dropdown > ,
257
251
{ attachTo : focusableContainer } ,
258
252
) ;
259
253
260
- wrapper . find ( '.toggle' ) . getDOMNode ( ) . focus ( ) ;
254
+ const toggle = wrapper . find ( '.toggle' ) . getDOMNode ( ) ;
255
+ toggle . focus ( ) ;
261
256
262
- wrapper . find ( '.toggle' ) . simulate ( 'keyDown' , { key : 'ArrowDown' } ) ;
257
+ simulant . fire ( toggle , 'keydown' , {
258
+ key : 'ArrowDown' ,
259
+ } ) ;
263
260
264
261
document . activeElement . should . equal (
265
- wrapper . find ( '.menu > button' ) . first ( ) . getDOMNode ( ) ,
262
+ wrapper . update ( ) . find ( '.menu > button' ) . first ( ) . getDOMNode ( ) ,
266
263
) ;
267
264
} ) ;
268
265
269
266
it ( 'when focused and closed sets focus on first menu item when the focusFirstItemOnShow is true' , ( ) => {
270
267
const wrapper = mount (
271
268
< Dropdown focusFirstItemOnShow >
272
- { ( { props } ) => (
273
- < div { ...props } >
274
- < Toggle > Child Title</ Toggle > ,
275
- < Menu >
276
- < button type = "button" > Item 1</ button >
277
- < button type = "button" > Item 2</ button >
278
- </ Menu >
279
- </ div >
280
- ) }
269
+ < div >
270
+ < Toggle > Child Title</ Toggle > ,
271
+ < Menu >
272
+ < button type = "button" > Item 1</ button >
273
+ < button type = "button" > Item 2</ button >
274
+ </ Menu >
275
+ </ div >
281
276
</ Dropdown > ,
282
277
{ attachTo : focusableContainer } ,
283
278
) ;
@@ -296,39 +291,42 @@ describe('<Dropdown>', () => {
296
291
attachTo : focusableContainer ,
297
292
} ) ;
298
293
299
- const firstItem = wrapper . find ( '.menu > button' ) . first ( ) ;
294
+ const firstItem = wrapper . find ( '.menu > button' ) . first ( ) . getDOMNode ( ) ;
300
295
301
- firstItem . getDOMNode ( ) . focus ( ) ;
302
- document . activeElement . should . equal ( firstItem . getDOMNode ( ) ) ;
296
+ firstItem . focus ( ) ;
297
+ document . activeElement . should . equal ( firstItem ) ;
303
298
304
- firstItem . simulate ( 'keyDown' , { key : 'Escape' } ) ;
299
+ act ( ( ) => {
300
+ simulant . fire ( firstItem , 'keydown' , {
301
+ key : 'Escape' ,
302
+ } ) ;
303
+ } ) ;
305
304
306
- document . activeElement . should . equal ( wrapper . find ( '.toggle' ) . getDOMNode ( ) ) ;
305
+ console . log ( document . activeElement ) ;
306
+ document . activeElement . should . equal (
307
+ wrapper . update ( ) . find ( '.toggle' ) . getDOMNode ( ) ,
308
+ ) ;
307
309
} ) ;
308
310
309
- it ( 'when open and the key "tab" is pressed the menu is closed and focus is progress to the next focusable element' , ( done ) => {
311
+ it ( 'when open and the key "tab" is pressed the menu is closed and focus is progress to the next focusable element' , ( ) => {
310
312
const wrapper = mount (
311
313
< div >
312
314
< SimpleDropdown defaultShow />
313
315
< input type = "text" id = "next-focusable" />
314
316
</ div > ,
315
- focusableContainer ,
317
+ { attachTo : focusableContainer } ,
316
318
) ;
317
319
318
- // Need to use Container instead of div above to make instance a composite
319
- // element, to make this call legal.
320
+ const toggle = wrapper . find ( '.toggle' ) . getDOMNode ( ) ;
320
321
321
- wrapper . find ( '. toggle' ) . simulate ( 'keyDown' , { key : 'Tab' } ) ;
322
+ toggle . focus ( ) ;
322
323
323
- setTimeout ( ( ) => {
324
- wrapper
325
- . find ( '.toggle' )
326
- . getDOMNode ( )
327
- . getAttribute ( 'aria-expanded' )
328
- . should . equal ( 'false' ) ;
329
- done ( ) ;
324
+ simulant . fire ( toggle , 'keydown' , {
325
+ key : 'Tab' ,
330
326
} ) ;
331
327
328
+ toggle . getAttribute ( 'aria-expanded' ) . should . equal ( 'false' ) ;
329
+
332
330
// simulating a tab event doesn't actually shift focus.
333
331
// at least that seems to be the case according to SO.
334
332
// hence no assert on the input having focus.
@@ -351,15 +349,13 @@ describe('<Dropdown>', () => {
351
349
352
350
mount (
353
351
< Dropdown show id = "test-id" >
354
- { ( ) => (
355
- < div >
356
- < Toggle > Child Title</ Toggle >
357
- < Menu popperConfig = { popper } >
358
- < button type = "button" > Item 1</ button >
359
- < button type = "button" > Item 2</ button >
360
- </ Menu >
361
- </ div >
362
- ) }
352
+ < div >
353
+ < Toggle > Child Title</ Toggle >
354
+ < Menu popperConfig = { popper } >
355
+ < button type = "button" > Item 1</ button >
356
+ < button type = "button" > Item 2</ button >
357
+ </ Menu >
358
+ </ div >
363
359
</ Dropdown > ,
364
360
) ;
365
361
0 commit comments