Skip to content

Commit

Permalink
Update the nested component test for modern times
Browse files Browse the repository at this point in the history
  • Loading branch information
jsnajdr committed Dec 16, 2022
1 parent 1c71955 commit db17eb3
Showing 1 changed file with 16 additions and 18 deletions.
34 changes: 16 additions & 18 deletions packages/data/src/components/use-select/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,7 @@ describe( 'useSelect', () => {
expect( screen.getByRole( 'status' ) ).toHaveTextContent( 'bar' );
} );

// TODO: this might be impossible to pull off in React 18 without `useSyncExternalStore`
it( 'avoid calling nested listener after unmounted', async () => {
it( 'does not rerender a nested component that is to be unmounted', () => {
registry.registerStore( 'toggler', {
reducer: ( state = false, action ) =>
action.type === 'TOGGLE' ? ! state : state,
Expand All @@ -134,16 +133,16 @@ describe( 'useSelect', () => {
const mapSelect = ( select ) => select( 'toggler' ).get();

const mapSelectChild = jest.fn( mapSelect );
function Child() {
const Child = jest.fn( () => {
const show = useSelect( mapSelectChild, [] );
return show ? 'yes' : 'no';
}
} );

const mapSelectParent = jest.fn( mapSelect );
function Parent() {
const Parent = jest.fn( () => {
const show = useSelect( mapSelectParent, [] );
return show ? <Child /> : 'none';
}
} );

render(
<RegistryProvider value={ registry }>
Expand All @@ -155,33 +154,32 @@ describe( 'useSelect', () => {
expect( screen.getByText( 'none' ) ).toBeInTheDocument();
expect( mapSelectParent ).toHaveBeenCalledTimes( 2 );
expect( mapSelectChild ).toHaveBeenCalledTimes( 0 );
expect( Parent ).toHaveBeenCalledTimes( 1 );
expect( Child ).toHaveBeenCalledTimes( 0 );

// act() does batched updates internally, i.e., any scheduled setStates or effects
// will be executed only after the dispatch finishes. But we want to opt out of
// batched updates here. We want all the setStates to be done synchronously, as the
// store listeners are called. The async/await code is a trick to do it: do the
// dispatch in a different event loop tick, where the batched updates are no longer active.
await act( async () => {
await Promise.resolve();
act( () => {
registry.dispatch( 'toggler' ).toggle();
} );

// Child was rendered and subscribed to the store, as the _second_ subscription.
expect( screen.getByText( 'yes' ) ).toBeInTheDocument();
expect( mapSelectParent ).toHaveBeenCalledTimes( 3 );
expect( mapSelectChild ).toHaveBeenCalledTimes( 2 );
expect( Parent ).toHaveBeenCalledTimes( 2 );
expect( Child ).toHaveBeenCalledTimes( 1 );

await act( async () => {
await Promise.resolve();
act( () => {
registry.dispatch( 'toggler' ).toggle();
} );

// Check that child was unmounted without any extra state update being performed on it.
// I.e., `mapSelectChild` was never called again, and no "state update on an unmounted
// component" warning was triggered.
// I.e., `mapSelectChild` was called again, and state update was scheduled, we cannot
// avoid that, but the state update is never executed and doesn't do a rerender.
expect( screen.getByText( 'none' ) ).toBeInTheDocument();
expect( mapSelectParent ).toHaveBeenCalledTimes( 4 );
expect( mapSelectChild ).toHaveBeenCalledTimes( 2 );
expect( mapSelectChild ).toHaveBeenCalledTimes( 3 );
expect( Parent ).toHaveBeenCalledTimes( 3 );
expect( Child ).toHaveBeenCalledTimes( 1 );
} );

describe( 'rerenders as expected with various mapSelect return types', () => {
Expand Down

1 comment on commit db17eb3

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/3714979723
📝 Reported issues:

Please sign in to comment.