1
1
/* eslint-disable no-undef */
2
- import { fireEvent , render } from '@testing-library/react' ;
2
+ import { act , fireEvent , render } from '@testing-library/react' ;
3
+ import { spyElementPrototypes } from 'rc-util/lib/test/domHook' ;
3
4
import React from 'react' ;
4
- import Menu , { MenuItem , SubMenu } from '../src' ;
5
+ import Menu , { MenuItem , MenuItemGroup , MenuRef , SubMenu } from '../src' ;
5
6
6
7
describe ( 'Focus' , ( ) => {
8
+ beforeAll ( ( ) => {
9
+ // Mock to force make menu item visible
10
+ spyElementPrototypes ( HTMLElement , {
11
+ offsetParent : {
12
+ get ( ) {
13
+ return this . parentElement ;
14
+ } ,
15
+ } ,
16
+ } ) ;
17
+ } ) ;
7
18
8
19
beforeEach ( ( ) => {
9
20
global . triggerProps = null ;
@@ -15,13 +26,15 @@ describe('Focus', () => {
15
26
jest . useRealTimers ( ) ;
16
27
} ) ;
17
28
18
- it ( 'Get focus' , ( ) => {
19
- const { container } = render (
20
- < Menu mode = "inline" openKeys = { [ 's' ] } >
21
- < SubMenu key = "s" title = "submenu" >
22
- < MenuItem key = "1" > 1</ MenuItem >
23
- </ SubMenu >
24
- </ Menu > ,
29
+ it ( 'Get focus' , async ( ) => {
30
+ const { container } = await act ( async ( ) =>
31
+ render (
32
+ < Menu mode = "inline" openKeys = { [ 's' ] } >
33
+ < SubMenu key = "s" title = "submenu" >
34
+ < MenuItem key = "1" > 1</ MenuItem >
35
+ </ SubMenu >
36
+ </ Menu > ,
37
+ ) ,
25
38
) ;
26
39
27
40
// Item focus
@@ -34,5 +47,149 @@ describe('Focus', () => {
34
47
fireEvent . focus ( container . querySelector ( '.rc-menu-submenu-title' ) ) ;
35
48
expect ( container . querySelector ( '.rc-menu-submenu-active' ) ) . toBeTruthy ( ) ;
36
49
} ) ;
50
+
51
+ it ( 'should support focus through ref' , async ( ) => {
52
+ const menuRef = React . createRef < MenuRef > ( ) ;
53
+ const { getByTestId } = await act ( async ( ) =>
54
+ render (
55
+ < Menu ref = { menuRef } >
56
+ < SubMenu key = "bamboo" title = "Disabled" disabled >
57
+ < MenuItem key = "bamboo-child" > Disabled child</ MenuItem >
58
+ </ SubMenu >
59
+ < MenuItem key = "light" data-testid = "first-focusable" >
60
+ Light
61
+ </ MenuItem >
62
+ </ Menu > ,
63
+ ) ,
64
+ ) ;
65
+
66
+ act ( ( ) => menuRef . current . focus ( ) ) ;
67
+
68
+ const firstFocusableItem = getByTestId ( 'first-focusable' ) ;
69
+ expect ( document . activeElement ) . toBe ( firstFocusableItem ) ;
70
+ expect ( firstFocusableItem ) . toHaveClass ( 'rc-menu-item-active' ) ;
71
+ } ) ;
72
+
73
+ it ( 'should focus active item through ref' , async ( ) => {
74
+ const menuRef = React . createRef < MenuRef > ( ) ;
75
+ const { getByTestId } = await act ( async ( ) =>
76
+ render (
77
+ < Menu ref = { menuRef } activeKey = "cat" >
78
+ < MenuItem key = "light" > Light</ MenuItem >
79
+ < MenuItem key = "cat" data-testid = "active-key" >
80
+ Cat
81
+ </ MenuItem >
82
+ </ Menu > ,
83
+ ) ,
84
+ ) ;
85
+ act ( ( ) => menuRef . current . focus ( ) ) ;
86
+
87
+ const activeKey = getByTestId ( 'active-key' ) ;
88
+ expect ( document . activeElement ) . toBe ( activeKey ) ;
89
+ expect ( activeKey ) . toHaveClass ( 'rc-menu-item-active' ) ;
90
+ } ) ;
91
+
92
+ it ( 'focus moves to the next accessible menu item if the first child is empty group' , async ( ) => {
93
+ const menuRef = React . createRef < MenuRef > ( ) ;
94
+ const { getByTestId } = await act ( async ( ) =>
95
+ render (
96
+ < Menu ref = { menuRef } >
97
+ < MenuItemGroup title = "group" key = "group" />
98
+ < SubMenu key = "bamboo" title = "Disabled" disabled >
99
+ < MenuItem key = "bamboo-child" > Disabled child</ MenuItem >
100
+ </ SubMenu >
101
+ < MenuItem key = "light" data-testid = "first-focusable" >
102
+ Light
103
+ </ MenuItem >
104
+ </ Menu > ,
105
+ ) ,
106
+ ) ;
107
+
108
+ act ( ( ) => menuRef . current . focus ( ) ) ;
109
+
110
+ const firstFocusableItem = getByTestId ( 'first-focusable' ) ;
111
+ expect ( document . activeElement ) . toBe ( firstFocusableItem ) ;
112
+ expect ( firstFocusableItem ) . toHaveClass ( 'rc-menu-item-active' ) ;
113
+ } ) ;
114
+
115
+ it ( 'focus moves to the next accessible group item if the first child is non-empty group' , async ( ) => {
116
+ const menuRef = React . createRef < MenuRef > ( ) ;
117
+ const { getByTestId } = await act ( async ( ) =>
118
+ render (
119
+ < Menu ref = { menuRef } >
120
+ < MenuItemGroup title = "group" key = "group" >
121
+ < MenuItem key = "group-child-1" disabled >
122
+ group-child-1
123
+ </ MenuItem >
124
+ < MenuItem key = "group-child-2" data-testid = "first-focusable" >
125
+ group-child-2
126
+ </ MenuItem >
127
+ </ MenuItemGroup >
128
+ < MenuItem key = "light" > Light</ MenuItem >
129
+ </ Menu > ,
130
+ ) ,
131
+ ) ;
132
+
133
+ act ( ( ) => menuRef . current . focus ( ) ) ;
134
+
135
+ const firstFocusableItem = getByTestId ( 'first-focusable' ) ;
136
+ expect ( document . activeElement ) . toBe ( firstFocusableItem ) ;
137
+ expect ( firstFocusableItem ) . toHaveClass ( 'rc-menu-item-active' ) ;
138
+ } ) ;
139
+
140
+ it ( 'focus moves to nested group item correctly' , async ( ) => {
141
+ const menuRef = React . createRef < MenuRef > ( ) ;
142
+ const { getByTestId } = await act ( async ( ) =>
143
+ render (
144
+ < Menu ref = { menuRef } >
145
+ < MenuItemGroup title = "group" key = "group" >
146
+ < MenuItem key = "group-child-1" disabled >
147
+ group-child-1
148
+ </ MenuItem >
149
+ < MenuItemGroup title = "nested group" key = "nested-group" >
150
+ < MenuItem key = "nested-group-child-1" disabled >
151
+ nested-group-child-1
152
+ </ MenuItem >
153
+ < MenuItem
154
+ key = "nested-group-child-2"
155
+ data-testid = "first-focusable"
156
+ >
157
+ nested-group-child-2
158
+ </ MenuItem >
159
+ </ MenuItemGroup >
160
+ < MenuItem key = "group-child-3" > group-child-3</ MenuItem >
161
+ </ MenuItemGroup >
162
+ </ Menu > ,
163
+ ) ,
164
+ ) ;
165
+
166
+ act ( ( ) => menuRef . current . focus ( ) ) ;
167
+
168
+ const firstFocusableItem = getByTestId ( 'first-focusable' ) ;
169
+ expect ( document . activeElement ) . toBe ( firstFocusableItem ) ;
170
+ expect ( firstFocusableItem ) . toHaveClass ( 'rc-menu-item-active' ) ;
171
+ } ) ;
172
+
173
+ it ( 'focus moves to submenu correctly' , async ( ) => {
174
+ const menuRef = React . createRef < MenuRef > ( ) ;
175
+ const { getByTestId, getByTitle } = await act ( async ( ) =>
176
+ render (
177
+ < Menu ref = { menuRef } >
178
+ < SubMenu key = "sub-menu-disabled" title = "Disabled" disabled >
179
+ < MenuItem key = "sub-menu-disabled-child" > Disabled child</ MenuItem >
180
+ </ SubMenu >
181
+ < SubMenu key = "sub-menu" data-testid = "sub-menu" title = "Submenu" >
182
+ < MenuItem key = "sub-menu-child-1" > Submenu child</ MenuItem >
183
+ </ SubMenu >
184
+ < MenuItem key = "light" > Light</ MenuItem >
185
+ </ Menu > ,
186
+ ) ,
187
+ ) ;
188
+
189
+ act ( ( ) => menuRef . current . focus ( ) ) ;
190
+
191
+ expect ( document . activeElement ) . toBe ( getByTitle ( 'Submenu' ) ) ;
192
+ expect ( getByTestId ( 'sub-menu' ) ) . toHaveClass ( 'rc-menu-submenu-active' ) ;
193
+ } ) ;
37
194
} ) ;
38
195
/* eslint-enable */
0 commit comments