Skip to content

Commit

Permalink
Fix unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ciampo committed Jun 28, 2023
1 parent 84d0707 commit fbeed05
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 43 deletions.
53 changes: 33 additions & 20 deletions packages/components/src/confirm-dialog/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import {
render,
screen,
fireEvent,
waitForElementToBeRemoved,
waitFor,
} from '@testing-library/react';
Expand All @@ -18,6 +17,18 @@ import { ConfirmDialog } from '..';
const noop = () => {};

describe( 'Confirm', () => {
let mockedDocumentHasFocus;

beforeEach( () => {
mockedDocumentHasFocus = jest
.spyOn( document, 'hasFocus' )
.mockImplementation( () => true );
} );

afterEach( () => {
mockedDocumentHasFocus.mockRestore();
} );

describe( 'Confirm component', () => {
describe( 'Structure', () => {
it( 'should render correctly', () => {
Expand Down Expand Up @@ -137,24 +148,27 @@ describe( 'Confirm', () => {
} );

it( 'should not render if dialog is closed by clicking the overlay, and the `onCancel` callback should be called', async () => {
const user = userEvent.setup();
const onCancel = jest.fn().mockName( 'onCancel()' );

render(
<ConfirmDialog onConfirm={ noop } onCancel={ onCancel }>
Are you sure?
</ConfirmDialog>
<div aria-label="Under the overlay">
<ConfirmDialog onConfirm={ noop } onCancel={ onCancel }>
Are you sure?
</ConfirmDialog>
</div>
);

const confirmDialog = screen.getByRole( 'dialog' );

//The overlay click is handled by detecting an onBlur from the modal frame.
// TODO: replace with `@testing-library/user-event`
fireEvent.blur( confirmDialog );
await user.click(
screen.getByLabelText( 'Under the overlay' )
);

await waitForElementToBeRemoved( confirmDialog );

expect( confirmDialog ).not.toBeInTheDocument();
expect( onCancel ).toHaveBeenCalled();
await waitFor( () => expect( onCancel ).toHaveBeenCalled() );
} );

it( 'should not render if dialog is closed by pressing `Escape`, and the `onCancel` callback should be called', async () => {
Expand Down Expand Up @@ -315,23 +329,22 @@ describe( 'Confirm', () => {
} );

it( 'should call the `onCancel` callback if the overlay is clicked', async () => {
const user = userEvent.setup();
const onCancel = jest.fn().mockName( 'onCancel()' );

render(
<ConfirmDialog
isOpen={ true }
onConfirm={ noop }
onCancel={ onCancel }
>
Are you sure?
</ConfirmDialog>
<div aria-label="Under the overlay">
<ConfirmDialog
isOpen={ true }
onConfirm={ noop }
onCancel={ onCancel }
>
Are you sure?
</ConfirmDialog>
</div>
);

const confirmDialog = screen.getByRole( 'dialog' );

//The overlay click is handled by detecting an onBlur from the modal frame.
// TODO: replace with `@testing-library/user-event`
fireEvent.blur( confirmDialog );
await user.click( screen.getByLabelText( 'Under the overlay' ) );

// Wait for a DOM side effect here, so that the `queueBlurCheck` in the
// `useFocusOutside` hook properly executes its timeout task.
Expand Down
68 changes: 45 additions & 23 deletions packages/compose/src/hooks/use-focus-outside/test/index.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,46 @@
/**
* External dependencies
*/
import { render, screen } from '@testing-library/react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

/**
* Internal dependencies
*/
import useFocusOutside from '../';

const FocusOutsideComponent = ( { onFocusOutside: callback } ) => (
<div>
{ /* Wrapper */ }
<div { ...useFocusOutside( callback ) }>
<input type="text" />
<button>Button inside the wrapper</button>
<iframe title="test-iframe">
<button>Inside the iframe</button>
</iframe>
const FocusOutsideComponent = ( { onFocusOutside: callback } ) => {
const focusOutsideProps = useFocusOutside( callback );

return (
<div>
{ /* Wrapper */ }
<div { ...focusOutsideProps }>
<input type="text" />
<button>Button inside the wrapper</button>
<iframe title="test-iframe">
<button>Inside the iframe</button>
</iframe>
</div>

<button>Button outside the wrapper</button>
</div>

<button>Button outside the wrapper</button>
</div>
);
);
};

describe( 'useFocusOutside', () => {
let mockedDocumentHasFocus;

beforeEach( () => {
mockedDocumentHasFocus = jest
.spyOn( document, 'hasFocus' )
.mockImplementation( () => true );
} );

afterEach( () => {
mockedDocumentHasFocus.mockRestore();
} );

it( 'should not call handler if focus shifts to element within component', async () => {
const mockOnFocusOutside = jest.fn();
const user = userEvent.setup();
Expand Down Expand Up @@ -72,24 +88,30 @@ describe( 'useFocusOutside', () => {
);

// Click and focus button inside the wrapper
await user.click(
screen.getByRole( 'button', { name: 'Button inside the wrapper' } )
);
const buttonInside = screen.getByRole( 'button', {
name: 'Button inside the wrapper',
} );
await user.click( buttonInside );

expect( mockOnFocusOutside ).not.toHaveBeenCalled();
// TODO: find a way to guarantee that the callback does not fire
await new Promise( ( r ) => setTimeout( r, 200 ) );

expect( mockOnFocusOutside ).not.toHaveBeenCalled();
// Click and focus button outside the wrapper
await user.click(
screen.getByRole( 'button', { name: 'Button outside the wrapper' } )
);
const buttonOutside = screen.getByRole( 'button', {
name: 'Button outside the wrapper',
} );
await user.click( buttonOutside );

expect( mockOnFocusOutside ).toHaveBeenCalled();
await waitFor( () =>
expect( mockOnFocusOutside ).toHaveBeenCalledTimes( 1 )
);
} );

it( 'should not call handler if focus shifts outside the component when the document does not have focus', async () => {
// 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.
const mockedDocumentHasFocus = jest
mockedDocumentHasFocus = jest
.spyOn( document, 'hasFocus' )
.mockImplementation( () => false );
const mockOnFocusOutside = jest.fn();
Expand Down

0 comments on commit fbeed05

Please sign in to comment.