From 30d67e84ab12783f90f33b419bace2b1ddb93035 Mon Sep 17 00:00:00 2001
From: Marin Atanasov <8436925+tyxla@users.noreply.github.com>
Date: Wed, 5 Oct 2022 12:13:01 +0200
Subject: [PATCH] Components: Refactor useFocusOutside to
@testing-library/react (#44698)
---
.../src/hooks/use-focus-outside/test/index.js | 89 +++++++++----------
1 file changed, 44 insertions(+), 45 deletions(-)
diff --git a/packages/compose/src/hooks/use-focus-outside/test/index.js b/packages/compose/src/hooks/use-focus-outside/test/index.js
index 23c7c36cf43e3..093bbb09ed1b3 100644
--- a/packages/compose/src/hooks/use-focus-outside/test/index.js
+++ b/packages/compose/src/hooks/use-focus-outside/test/index.js
@@ -1,7 +1,8 @@
/**
* External dependencies
*/
-import TestUtils from 'react-dom/test-utils';
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
/**
* WordPress dependencies
@@ -12,38 +13,24 @@ import { Component } from '@wordpress/element';
* Internal dependencies
*/
import useFocusOutside from '../';
-import ReactDOM from 'react-dom';
-let wrapper, onFocusOutside;
+let onFocusOutside;
describe( 'useFocusOutside', () => {
let origHasFocus;
const FocusOutsideComponent = ( { onFocusOutside: callback } ) => (
-
+
);
- // This is needed because TestUtils does not accept a stateless component.
- // anything run through a HOC ends up as a stateless component.
- const getTestComponent = ( WrappedComponent, props ) => {
- class TestComponent extends Component {
- render() {
- return ;
- }
+ class TestComponent extends Component {
+ render() {
+ return ;
}
- return ;
- };
-
- const simulateEvent = ( event, index = 0 ) => {
- const element = TestUtils.scryRenderedDOMComponentsWithTag(
- wrapper,
- 'input'
- );
- TestUtils.Simulate[ event ]( element[ index ] );
- };
+ }
beforeEach( () => {
// Mock document.hasFocus() to always be true for testing
@@ -52,9 +39,6 @@ describe( 'useFocusOutside', () => {
document.hasFocus = () => true;
onFocusOutside = jest.fn();
- wrapper = TestUtils.renderIntoDocument(
- getTestComponent( FocusOutsideComponent, { onFocusOutside } )
- );
} );
afterEach( () => {
@@ -62,24 +46,31 @@ describe( 'useFocusOutside', () => {
} );
it( 'should not call handler if focus shifts to element within component', () => {
- simulateEvent( 'focus' );
- simulateEvent( 'blur' );
- simulateEvent( 'focus', 1 );
+ render( );
+
+ const input = screen.getByRole( 'textbox' );
+ const button = screen.getByRole( 'button' );
+
+ input.focus();
+ input.blur();
+ button.focus();
jest.runAllTimers();
expect( onFocusOutside ).not.toHaveBeenCalled();
} );
- it( 'should not call handler if focus transitions via click to button', () => {
- simulateEvent( 'focus' );
- simulateEvent( 'mouseDown', 1 );
- simulateEvent( 'blur' );
+ it( 'should not call handler if focus transitions via click to button', async () => {
+ const user = userEvent.setup( {
+ advanceTimers: jest.advanceTimersByTime,
+ } );
+ render( );
+
+ const input = screen.getByRole( 'textbox' );
+ const button = screen.getByRole( 'button' );
- // In most browsers, the input at index 1 would receive a focus event
- // at this point, but this is not guaranteed, which is the intention of
- // the normalization behavior tested here.
- simulateEvent( 'mouseUp', 1 );
+ input.focus();
+ await user.click( button );
jest.runAllTimers();
@@ -87,8 +78,11 @@ describe( 'useFocusOutside', () => {
} );
it( 'should call handler if focus doesn’t shift to element within component', () => {
- simulateEvent( 'focus' );
- simulateEvent( 'blur' );
+ render( );
+
+ const input = screen.getByRole( 'textbox' );
+ input.focus();
+ input.blur();
jest.runAllTimers();
@@ -96,12 +90,15 @@ describe( 'useFocusOutside', () => {
} );
it( 'should not call handler if focus shifts outside the component when the document does not have focus', () => {
+ render( );
+
// Force document.hasFocus() to return false to simulate the window/document losing focus
// See https://developer.mozilla.org/en-US/docs/Web/API/Document/hasFocus.
document.hasFocus = () => false;
- simulateEvent( 'focus' );
- simulateEvent( 'blur' );
+ const input = screen.getByRole( 'textbox' );
+ input.focus();
+ input.blur();
jest.runAllTimers();
@@ -109,14 +106,16 @@ describe( 'useFocusOutside', () => {
} );
it( 'should cancel check when unmounting while queued', () => {
- simulateEvent( 'focus' );
- simulateEvent( 'input' );
-
- ReactDOM.unmountComponentAtNode(
- // eslint-disable-next-line react/no-find-dom-node
- ReactDOM.findDOMNode( wrapper ).parentNode
+ const { rerender } = render(
+
);
+ const input = screen.getByRole( 'textbox' );
+ input.focus();
+ input.blur();
+
+ rerender( );
+
jest.runAllTimers();
expect( onFocusOutside ).not.toHaveBeenCalled();