10
10
* governing permissions and limitations under the License.
11
11
*/
12
12
import { act , fireEvent , render , renderHook , screen , waitFor } from '@react-spectrum/test-utils' ;
13
+ import { addWindowFocusTracking , useFocusVisible , useFocusVisibleListener } from '../' ;
13
14
import { hasSetupGlobalListeners } from '../src/useFocusVisible' ;
14
15
import React from 'react' ;
15
16
import { render as ReactDOMRender } from 'react-dom' ;
16
- import { setupFocus , useFocusVisible , useFocusVisibleListener } from '../' ;
17
17
18
18
function Example ( props ) {
19
19
const { isFocusVisible} = useFocusVisible ( ) ;
20
- return < div id = { props . id } > example{ isFocusVisible && '-focusVisible' } </ div > ;
20
+ return < div { ... props } > example{ isFocusVisible && '-focusVisible' } </ div > ;
21
21
}
22
22
23
23
function toggleBrowserTabs ( ) {
@@ -103,7 +103,7 @@ describe('useFocusVisible', function () {
103
103
iframe . contentWindow . document . body . appendChild ( iframeRoot ) ;
104
104
} ) ;
105
105
106
- afterEach ( ( ) => {
106
+ afterEach ( async ( ) => {
107
107
fireEvent ( iframe . contentWindow , new Event ( 'beforeunload' ) ) ;
108
108
iframe . remove ( ) ;
109
109
} ) ;
@@ -120,7 +120,7 @@ describe('useFocusVisible', function () {
120
120
expect ( el . textContent ) . toBe ( 'example' ) ;
121
121
122
122
// Setup focus in iframe
123
- setupFocus ( iframeRoot ) ;
123
+ addWindowFocusTracking ( iframeRoot ) ;
124
124
expect ( el . textContent ) . toBe ( 'example' ) ;
125
125
126
126
// Focus in iframe after setupFocus
@@ -129,16 +129,19 @@ describe('useFocusVisible', function () {
129
129
} ) ;
130
130
131
131
it ( 'removes event listeners on beforeunload' , async function ( ) {
132
- ReactDOMRender ( < Example id = "iframe-example" /> , iframeRoot ) ;
133
- setupFocus ( iframeRoot ) ;
132
+ let tree = render ( < Example data-testid = "iframe-example" /> , iframeRoot ) ;
134
133
135
134
await waitFor ( ( ) => {
136
- expect ( document . querySelector ( 'iframe' ) . contentWindow . document . body . querySelector ( 'div[id="iframe -example"] ') ) . toBeTruthy ( ) ;
135
+ expect ( tree . getByTestId ( 'iframe-example' ) ) . toBeTruthy ( ) ;
137
136
} ) ;
138
- const el = document . querySelector ( 'iframe' ) . contentWindow . document . body . querySelector ( 'div[id="iframe-example"]' ) ;
137
+ const el = tree . getByTestId ( 'iframe-example' ) ;
138
+ // trigger keyboard focus
139
+ fireEvent . keyDown ( el , { key : 'a' } ) ;
140
+ fireEvent . keyUp ( el , { key : 'a' } ) ;
139
141
expect ( el . textContent ) . toBe ( 'example-focusVisible' ) ;
140
142
141
143
fireEvent . mouseDown ( el ) ;
144
+ fireEvent . mouseUp ( el ) ;
142
145
expect ( el . textContent ) . toBe ( 'example' ) ;
143
146
144
147
// Focus events after beforeunload no longer work
@@ -147,14 +150,36 @@ describe('useFocusVisible', function () {
147
150
expect ( el . textContent ) . toBe ( 'example' ) ;
148
151
} ) ;
149
152
153
+ it ( 'removes event listeners using teardown function' , async function ( ) {
154
+ let tree = render ( < Example data-testid = "iframe-example" /> , iframeRoot ) ;
155
+ let tearDown = addWindowFocusTracking ( iframeRoot ) ;
156
+
157
+ await waitFor ( ( ) => {
158
+ expect ( tree . getByTestId ( 'iframe-example' ) ) . toBeTruthy ( ) ;
159
+ } ) ;
160
+ const el = tree . getByTestId ( 'iframe-example' ) ;
161
+ // trigger keyboard focus
162
+ fireEvent . keyDown ( el , { key : 'a' } ) ;
163
+ fireEvent . keyUp ( el , { key : 'a' } ) ;
164
+ expect ( el . textContent ) . toBe ( 'example-focusVisible' ) ;
165
+
166
+ fireEvent . mouseDown ( el ) ;
167
+ fireEvent . mouseUp ( el ) ;
168
+ expect ( el . textContent ) . toBe ( 'example' ) ;
169
+
170
+ tearDown ( ) ;
171
+ fireEvent . focus ( iframe . contentWindow . document . body ) ;
172
+ expect ( el . textContent ) . toBe ( 'example' ) ;
173
+ } ) ;
174
+
150
175
it ( 'removes the window object from the hasSetupGlobalListeners object on beforeunload' , async function ( ) {
151
176
ReactDOMRender ( < Example id = "iframe-example" /> , iframeRoot ) ;
152
177
expect ( hasSetupGlobalListeners . size ) . toBe ( 1 ) ;
153
178
expect ( hasSetupGlobalListeners . get ( window ) ) . toBeTruthy ( ) ;
154
179
expect ( hasSetupGlobalListeners . get ( iframe . contentWindow ) ) . toBeFalsy ( ) ;
155
180
156
181
// After setup focus
157
- setupFocus ( iframeRoot ) ;
182
+ addWindowFocusTracking ( iframeRoot ) ;
158
183
expect ( hasSetupGlobalListeners . size ) . toBe ( 2 ) ;
159
184
expect ( hasSetupGlobalListeners . get ( window ) ) . toBeTruthy ( ) ;
160
185
expect ( hasSetupGlobalListeners . get ( iframe . contentWindow ) ) . toBeTruthy ( ) ;
@@ -166,9 +191,27 @@ describe('useFocusVisible', function () {
166
191
expect ( hasSetupGlobalListeners . get ( iframe . contentWindow ) ) . toBeFalsy ( ) ;
167
192
} ) ;
168
193
194
+ it ( 'removes the window object from the hasSetupGlobalListeners object if we preemptively tear down' , async function ( ) {
195
+ ReactDOMRender ( < Example id = "iframe-example" /> , iframeRoot ) ;
196
+ expect ( hasSetupGlobalListeners . size ) . toBe ( 1 ) ;
197
+ expect ( hasSetupGlobalListeners . get ( window ) ) . toBeTruthy ( ) ;
198
+ expect ( hasSetupGlobalListeners . get ( iframe . contentWindow ) ) . toBeFalsy ( ) ;
199
+
200
+ // After setup focus
201
+ let tearDown = addWindowFocusTracking ( iframeRoot ) ;
202
+ expect ( hasSetupGlobalListeners . size ) . toBe ( 2 ) ;
203
+ expect ( hasSetupGlobalListeners . get ( window ) ) . toBeTruthy ( ) ;
204
+ expect ( hasSetupGlobalListeners . get ( iframe . contentWindow ) ) . toBeTruthy ( ) ;
205
+
206
+ tearDown ( ) ;
207
+ expect ( hasSetupGlobalListeners . size ) . toBe ( 1 ) ;
208
+ expect ( hasSetupGlobalListeners . get ( window ) ) . toBeTruthy ( ) ;
209
+ expect ( hasSetupGlobalListeners . get ( iframe . contentWindow ) ) . toBeFalsy ( ) ;
210
+ } ) ;
211
+
169
212
it ( 'returns positive isFocusVisible result after toggling browser tabs after keyboard navigation' , async function ( ) {
170
213
ReactDOMRender ( < Example id = "iframe-example" /> , iframeRoot ) ;
171
- setupFocus ( iframeRoot ) ;
214
+ addWindowFocusTracking ( iframeRoot ) ;
172
215
173
216
// Fire focus in iframe
174
217
await waitFor ( ( ) => {
@@ -188,7 +231,7 @@ describe('useFocusVisible', function () {
188
231
189
232
it ( 'returns negative isFocusVisible result after toggling browser tabs without prior keyboard navigation' , async function ( ) {
190
233
ReactDOMRender ( < Example id = "iframe-example" /> , iframeRoot ) ;
191
- setupFocus ( iframeRoot ) ;
234
+ addWindowFocusTracking ( iframeRoot ) ;
192
235
193
236
// Fire focus in iframe
194
237
await waitFor ( ( ) => {
@@ -206,7 +249,7 @@ describe('useFocusVisible', function () {
206
249
207
250
it ( 'returns positive isFocusVisible result after toggling browser window after keyboard navigation' , async function ( ) {
208
251
ReactDOMRender ( < Example id = "iframe-example" /> , iframeRoot ) ;
209
- setupFocus ( iframeRoot ) ;
252
+ addWindowFocusTracking ( iframeRoot ) ;
210
253
211
254
// Fire focus in iframe
212
255
await waitFor ( ( ) => {
@@ -225,7 +268,7 @@ describe('useFocusVisible', function () {
225
268
226
269
it ( 'returns negative isFocusVisible result after toggling browser window without prior keyboard navigation' , async function ( ) {
227
270
ReactDOMRender ( < Example id = "iframe-example" /> , iframeRoot ) ;
228
- setupFocus ( iframeRoot ) ;
271
+ addWindowFocusTracking ( iframeRoot ) ;
229
272
230
273
// Fire focus in iframe
231
274
await waitFor ( ( ) => {
0 commit comments