diff --git a/packages/compose/src/hooks/use-merge-refs/test/index.js b/packages/compose/src/hooks/use-merge-refs/test/index.js
index 3da6b1e991a7c2..0c156abe0c0a5b 100644
--- a/packages/compose/src/hooks/use-merge-refs/test/index.js
+++ b/packages/compose/src/hooks/use-merge-refs/test/index.js
@@ -14,141 +14,135 @@ import { useCallback } from '@wordpress/element';
import useMergeRefs from '../';
describe( 'useMergeRefs', () => {
- beforeAll( () => {
- const rootElement = document.createElement( 'div' );
- rootElement.id = 'root';
- document.body.appendChild( rootElement );
- } );
-
- it( 'should work', () => {
- const renderCallback = jest.fn();
- const refCallback1 = jest.fn();
-
- function MergedRefs() {
- renderCallback();
- return (
-
- );
+ // Setup
+ // =====
+ //
+ // A component with two merged ref callbacks. The second has a dependency,
+ // the first does not. We expect the one with the dependency to be called
+ // with null in the old function and the node in the new function. We don't
+ // expect the first ref callback to be called **unless** the node changes.
+ // There's a prop controlling the tag name, which can be used to trigger a
+ // node change. In that case we expect both ref callbacks to be called with
+ // null in the old function and the **new** node in the new function.
+ //
+ // The history of all functions is recorded. Note that a new function is
+ // created on every render, which will all be tracked. Some functions are
+ // never expected to be called on subsequent renders if no callback
+ // dependency updates!
+
+ function renderCallback( args ) {
+ renderCallback.history.push( args );
+ }
+
+ renderCallback.history = [];
+
+ function MergedRefs( { count, tagName: TagName = 'div' } ) {
+ function refCallback1( value ) {
+ refCallback1.history.push( value );
}
- const rootElement = document.getElementById( 'root' );
+ refCallback1.history = [];
- ReactDOM.render( , rootElement );
+ function refCallback2( value ) {
+ refCallback2.history.push( value );
+ }
- expect( renderCallback ).toHaveBeenCalledTimes( 1 );
- expect( refCallback1 ).toHaveBeenCalledTimes( 1 );
- expect( refCallback1 ).toHaveBeenCalledWith(
- rootElement.firstElementChild
- );
+ refCallback2.history = [];
- ReactDOM.render( , rootElement );
+ renderCallback( [ refCallback1.history, refCallback2.history ] );
- expect( renderCallback ).toHaveBeenCalledTimes( 2 );
- expect( refCallback1 ).toHaveBeenCalledTimes( 1 );
- expect( refCallback1 ).toHaveBeenCalledWith(
- rootElement.firstElementChild
+ return (
+
);
+ }
+
+ beforeEach( () => {
+ const rootElement = document.createElement( 'div' );
+ rootElement.id = 'root';
+ document.body.appendChild( rootElement );
} );
- it( 'should work with 2', () => {
- const refCallback1 = jest.fn();
- const refCallback2 = jest.fn();
-
- function MergedRefs() {
- return (
-
- );
- }
+ afterEach( () => {
+ // Reset all history and DOM.
+ renderCallback.history = [];
+ document.body.innerHTML = '';
+ } );
+ it( 'should work', () => {
const rootElement = document.getElementById( 'root' );
ReactDOM.render( , rootElement );
- expect( refCallback1 ).toHaveBeenCalledTimes( 1 );
- expect( refCallback1 ).toHaveBeenCalledWith(
- rootElement.firstElementChild
- );
- expect( refCallback2 ).toHaveBeenCalledTimes( 1 );
- expect( refCallback2 ).toHaveBeenCalledWith(
- rootElement.firstElementChild
- );
- } );
-
- it( 'should work for node change', () => {
- const renderCallback = jest.fn();
-
- function refCallback1( value ) {
- refCallback1.history = refCallback1.history || [];
- refCallback1.history.push( value );
- }
-
- function MergedRefs( { tagName: TagName = 'div' } ) {
- renderCallback();
- return (
-
- );
- }
+ const originalElement = rootElement.firstElementChild;
- const rootElement = document.getElementById( 'root' );
+ // Render 1: both initial callback functions should be called with node.
+ expect( renderCallback.history ).toEqual( [
+ [ [ originalElement ], [ originalElement ] ],
+ ] );
ReactDOM.render( , rootElement );
- const originalElement = rootElement.firstElementChild;
-
- expect( renderCallback ).toHaveBeenCalledTimes( 1 );
- expect( refCallback1.history ).toEqual( [ originalElement ] );
+ // Render 2: the new callback functions should not be called! There has
+ // been no dependency change.
+ expect( renderCallback.history ).toEqual( [
+ [ [ originalElement ], [ originalElement ] ],
+ [ [], [] ],
+ ] );
- ReactDOM.render( , rootElement );
+ ReactDOM.render( null, rootElement );
- expect( renderCallback ).toHaveBeenCalledTimes( 2 );
- expect( refCallback1.history ).toEqual( [
- originalElement,
- null,
- rootElement.firstElementChild,
+ // Unmount: the initial callback functions should receive null.
+ expect( renderCallback.history ).toEqual( [
+ [
+ [ originalElement, null ],
+ [ originalElement, null ],
+ ],
+ [ [], [] ],
] );
} );
- it( 'should work with 2 different deps', () => {
- function renderCallback( args ) {
- renderCallback.history.push( args );
- }
+ it( 'should work for node change', () => {
+ const rootElement = document.getElementById( 'root' );
- renderCallback.history = [];
+ ReactDOM.render( , rootElement );
- function MergedRefs( { count } ) {
- function refCallback1( value ) {
- refCallback1.history.push( value );
- }
+ const originalElement = rootElement.firstElementChild;
- refCallback1.history = [];
+ ReactDOM.render( , rootElement );
- function refCallback2( value ) {
- refCallback2.history.push( value );
- }
+ const newElement = rootElement.firstElementChild;
- refCallback2.history = [];
+ // After a render with the original element and a second render with the
+ // new element, expect the initial callback functions to be called with
+ // the original element, then null, then the new element.
+ // Again, the new callback functions should not be called! There has
+ // been no dependency change.
+ expect( renderCallback.history ).toEqual( [
+ [
+ [ originalElement, null, newElement ],
+ [ originalElement, null, newElement ],
+ ],
+ [ [], [] ],
+ ] );
- renderCallback( [ refCallback1.history, refCallback2.history ] );
+ ReactDOM.render( null, rootElement );
- return (
-
- );
- }
+ // Unmount: the initial callback functions should receive null.
+ expect( renderCallback.history ).toEqual( [
+ [
+ [ originalElement, null, newElement, null ],
+ [ originalElement, null, newElement, null ],
+ ],
+ [ [], [] ],
+ ] );
+ } );
+ it( 'should work with dependencies', () => {
const rootElement = document.getElementById( 'root' );
ReactDOM.render( , rootElement );
@@ -161,57 +155,28 @@ describe( 'useMergeRefs', () => {
ReactDOM.render( , rootElement );
+ // After a second render with a dependency change, expect the inital
+ // callback function to be called with null and the new callback
+ // function to be called with the original node. Note that for callback
+ // one no dependencies have changed.
+ expect( renderCallback.history ).toEqual( [
+ [ [ originalElement ], [ originalElement, null ] ],
+ [ [], [ originalElement ] ],
+ ] );
+
+ ReactDOM.render( null, rootElement );
+
+ // Unmount: current callback functions should be called with null.
expect( renderCallback.history ).toEqual( [
[
- // Expect the "old" callback 1 to be called with the node.
- [ originalElement ],
- // Expect the "old" callback 2 to be called with the node, then
- // `null`.
+ [ originalElement, null ],
[ originalElement, null ],
],
- [
- // Don't expect the "new" callback 1 to be called.
- // No dependencies or node have changed.
- [],
- // Expect the "new" callback 2 to be called with the node since
- // a dependency has updated.
- [ originalElement ],
- ],
+ [ [], [ originalElement, null ] ],
] );
} );
it( 'should simultaneously update node and dependencies', () => {
- function renderCallback( args ) {
- renderCallback.history.push( args );
- }
-
- renderCallback.history = [];
-
- function MergedRefs( { count, tagName: TagName = 'div' } ) {
- function refCallback1( value ) {
- refCallback1.history.push( value );
- }
-
- refCallback1.history = [];
-
- function refCallback2( value ) {
- refCallback2.history.push( value );
- }
-
- refCallback2.history = [];
-
- renderCallback( [ refCallback1.history, refCallback2.history ] );
-
- return (
-
- );
- }
-
const rootElement = document.getElementById( 'root' );
ReactDOM.render( , rootElement );
@@ -227,65 +192,30 @@ describe( 'useMergeRefs', () => {
rootElement
);
+ const newElement = rootElement.firstElementChild;
+
+ // Both the node changes and the dependencies update for the second
+ // callback, so expect the old callback function to be called with null
+ // and the new callback function to be called with the **new** node.
+ // For the first callback, we expect the initial function to be called
+ // with null and then the new node since no dependencies have changed.
expect( renderCallback.history ).toEqual( [
[
- // Expect the "old" callback 1 to be called with the node,
- // then null and then the new node.
- [ originalElement, null, rootElement.firstElementChild ],
- // Expect the "old" callback 2 to be called with the node, then
- // `null`.
+ [ originalElement, null, newElement ],
[ originalElement, null ],
],
- [
- // Don't expect the "new" callback 1 to be called since
- // No dependencies or node have changed.
- [],
- // Expect the "new" callback 2 to be called with the node since
- // a dependency has updated.
- [ rootElement.firstElementChild ],
- ],
+ [ [], [ newElement ] ],
] );
- } );
-
- it( 'should unmount', () => {
- function renderCallback( args ) {
- renderCallback.history.push( args );
- }
-
- renderCallback.history = [];
-
- function MergedRefs() {
- function refCallback1( value ) {
- refCallback1.history.push( value );
- }
-
- refCallback1.history = [];
-
- renderCallback( [ refCallback1.history ] );
-
- return (
-
- );
- }
-
- const rootElement = document.getElementById( 'root' );
-
- ReactDOM.render( , rootElement );
-
- const originalElement = rootElement.firstElementChild;
-
- expect( renderCallback.history ).toEqual( [ [ [ originalElement ] ] ] );
ReactDOM.render( null, rootElement );
+ // Unmount: current callback functions should be called with null.
expect( renderCallback.history ).toEqual( [
[
- // Expect the "old" callback 1 to be called with the node,
- // then null and then the new node.
+ [ originalElement, null, newElement, null ],
[ originalElement, null ],
],
+ [ [], [ newElement, null ] ],
] );
} );
} );