Skip to content

Commit

Permalink
useSelect: add unit tests for usage without deps (#40732)
Browse files Browse the repository at this point in the history
* useSelect: add unit tests for usage without deps

* Add an explainer comment
  • Loading branch information
jsnajdr committed May 5, 2022
1 parent 5bc8ac0 commit 57fdc69
Showing 1 changed file with 71 additions and 0 deletions.
71 changes: 71 additions & 0 deletions packages/data/src/components/use-select/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1025,4 +1025,75 @@ describe( 'useSelect', () => {
expect( TestComponent ).toHaveBeenCalledTimes( 2 );
} );
} );

describe( 'usage without dependencies array', () => {
function registerStore( name, initial ) {
registry.registerStore( name, {
reducer: ( s = initial, a ) => ( a.type === 'inc' ? s + 1 : s ),
actions: { inc: () => ( { type: 'inc' } ) },
selectors: { get: ( s ) => s },
} );
}

it( 'does not memoize the callback when there are no deps', () => {
registerStore( 'store', 1 );

const Status = ( { multiple } ) => {
const count = useSelect(
( select ) => select( 'store' ).get() * multiple
);
return <div role="status">{ count }</div>;
};

const App = ( { multiple } ) => (
<RegistryProvider value={ registry }>
<Status multiple={ multiple } />
</RegistryProvider>
);

const rendered = render( <App multiple={ 1 } /> );
expect( rendered.getByRole( 'status' ) ).toHaveTextContent( 1 );

// Check that the most recent value of `multiple` is used to render:
// the old callback wasn't memoized and there is no stale closure problem.
rendered.rerender( <App multiple={ 2 } /> );
expect( rendered.getByRole( 'status' ) ).toHaveTextContent( 2 );
} );

it( 'subscribes only stores used by the initial callback', () => {
registerStore( 'counter-1', 1 );
registerStore( 'counter-2', 10 );

const Status = ( { store } ) => {
const count = useSelect( ( select ) => select( store ).get() );
return <div role="status">{ count }</div>;
};

const App = ( { store } ) => (
<RegistryProvider value={ registry }>
<Status store={ store } />
</RegistryProvider>
);

// initial render with counter-1
const rendered = render( <App store="counter-1" /> );
expect( rendered.getByRole( 'status' ) ).toHaveTextContent( 1 );

// update from counter-1
act( () => {
registry.dispatch( 'counter-1' ).inc();
} );
expect( rendered.getByRole( 'status' ) ).toHaveTextContent( 2 );

// rerender with counter-2
rendered.rerender( <App store="counter-2" /> );
expect( rendered.getByRole( 'status' ) ).toHaveTextContent( 10 );

// update from counter-2 is ignored because component is subcribed only to counter-1
act( () => {
registry.dispatch( 'counter-2' ).inc();
} );
expect( rendered.getByRole( 'status' ) ).toHaveTextContent( 10 );
} );
} );
} );

0 comments on commit 57fdc69

Please sign in to comment.