Skip to content

Commit

Permalink
Block Editor: Flatten LinkControl components by mocking useSelect for…
Browse files Browse the repository at this point in the history
… tests (#19705)

* Block Editor: Flatten LinkControl components by mocking useSelect for tests

* Block Editor: Inline LinkControl rendering

* Block Editor: Mock useSelect by relative file import
  • Loading branch information
aduth authored Jan 16, 2020
1 parent dbe6466 commit 80e1a5a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 83 deletions.
22 changes: 8 additions & 14 deletions packages/block-editor/src/components/link-control/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,21 @@ import LinkControlSearchInput from './search-input';

const MODE_EDIT = 'edit';

export function LinkControl( {
function LinkControl( {
value,
settings,
onChange = noop,
showInitialSuggestions,
fetchSearchSuggestions,
} ) {
const instanceId = useInstanceId( LinkControl );
const [ inputValue, setInputValue ] = useState( '' );
const [ isEditingLink, setIsEditingLink ] = useState( ! value || ! value.url );
const { fetchSearchSuggestions } = useSelect( ( select ) => {
const { getSettings } = select( 'core/block-editor' );
return {
fetchSearchSuggestions: getSettings().__experimentalFetchLinkSuggestions,
};
}, [] );

// Handlers

Expand Down Expand Up @@ -226,15 +231,4 @@ export function LinkControl( {
);
}

function ConnectedLinkControl( props ) {
const { fetchSearchSuggestions } = useSelect( ( select ) => {
const { getSettings } = select( 'core/block-editor' );
return {
fetchSearchSuggestions: getSettings().__experimentalFetchLinkSuggestions,
};
}, [] );

return <LinkControl fetchSearchSuggestions={ fetchSearchSuggestions } { ...props } />;
}

export default ConnectedLinkControl;
export default LinkControl;
98 changes: 29 additions & 69 deletions packages/block-editor/src/components/link-control/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ import { UP, DOWN, ENTER } from '@wordpress/keycodes';
/**
* Internal dependencies
*/
import { LinkControl } from '../index';
import LinkControl from '../';
import { fauxEntitySuggestions, fetchFauxEntitySuggestions } from './fixtures';

const mockFetchSearchSuggestions = jest.fn();

jest.mock( '@wordpress/data/src/components/use-select', () => () => ( {
fetchSearchSuggestions: mockFetchSearchSuggestions,
} ) );

/**
* Wait for next tick of event loop. This is required
* because the `fetchSearchSuggestions` Promise will
Expand All @@ -33,13 +39,15 @@ beforeEach( () => {
// setup a DOM element as a render target
container = document.createElement( 'div' );
document.body.appendChild( container );
mockFetchSearchSuggestions.mockImplementation( fetchFauxEntitySuggestions );
} );

afterEach( () => {
// cleanup on exiting
unmountComponentAtNode( container );
container.remove();
container = null;
mockFetchSearchSuggestions.mockReset();
} );

describe( 'Basic rendering', () => {
Expand Down Expand Up @@ -71,12 +79,10 @@ describe( 'Searching for a link', () => {
resolver = resolve;
} );

mockFetchSearchSuggestions.mockImplementation( fauxRequest );

act( () => {
render(
<LinkControl
fetchSearchSuggestions={ fauxRequest }
/>, container
);
render( <LinkControl />, container );
} );

// Search Input UI
Expand Down Expand Up @@ -115,11 +121,7 @@ describe( 'Searching for a link', () => {
const firstFauxSuggestion = first( fauxEntitySuggestions );

act( () => {
render(
<LinkControl
fetchSearchSuggestions={ fetchFauxEntitySuggestions }
/>, container
);
render( <LinkControl />, container );
} );

// Search Input UI
Expand Down Expand Up @@ -153,11 +155,7 @@ describe( 'Searching for a link', () => {
[ 'ThisCouldAlsoBeAValidURL' ],
] )( 'should display a URL suggestion as a default fallback for the search term "%s" which could potentially be a valid url.', async ( searchTerm ) => {
act( () => {
render(
<LinkControl
fetchSearchSuggestions={ fetchFauxEntitySuggestions }
/>, container
);
render( <LinkControl />, container );
} );

// Search Input UI
Expand Down Expand Up @@ -190,11 +188,7 @@ describe( 'Searching for a link', () => {
const searchTerm = 'Hello world';

act( () => {
render(
<LinkControl
fetchSearchSuggestions={ fetchFauxEntitySuggestions }
/>, container
);
render( <LinkControl />, container );
} );

let searchResultElements;
Expand Down Expand Up @@ -242,11 +236,7 @@ describe( 'Manual link entry', () => {
[ 'www.wordpress.org' ], // usage of "www"
] )( 'should display a single suggestion result when the current input value is URL-like (eg: %s)', async ( searchTerm ) => {
act( () => {
render(
<LinkControl
fetchSearchSuggestions={ fetchFauxEntitySuggestions }
/>, container
);
render( <LinkControl />, container );
} );

// Search Input UI
Expand Down Expand Up @@ -279,9 +269,7 @@ describe( 'Manual link entry', () => {
] )( 'should recognise "%s" as a %s link and handle as manual entry by displaying a single suggestion', async ( searchTerm, searchType ) => {
act( () => {
render(
<LinkControl
fetchSearchSuggestions={ fetchFauxEntitySuggestions }
/>, container
<LinkControl />, container
);
} );

Expand Down Expand Up @@ -311,15 +299,11 @@ describe( 'Manual link entry', () => {

describe( 'Default search suggestions', () => {
it( 'should display a list of initial search suggestions when there is no search value or suggestions', async () => {
const searchSuggestionsSpy = jest.fn( fetchFauxEntitySuggestions );
const expectedResultsLength = 3; // set within `LinkControl`

act( () => {
render(
<LinkControl
fetchSearchSuggestions={ searchSuggestionsSpy }
showInitialSuggestions={ true }
/>, container
<LinkControl showInitialSuggestions />, container
);
} );

Expand All @@ -341,7 +325,7 @@ describe( 'Default search suggestions', () => {
// Ensure only called once as a guard against potential infinite
// re-render loop within `componentDidUpdate` calling `updateSuggestions`
// which has calls to `setState` within it.
expect( searchSuggestionsSpy ).toHaveBeenCalledTimes( 1 );
expect( mockFetchSearchSuggestions ).toHaveBeenCalledTimes( 1 );

// Verify the search results already display the initial suggestions
expect( initialSearchResultElements ).toHaveLength( expectedResultsLength );
Expand All @@ -350,7 +334,6 @@ describe( 'Default search suggestions', () => {
} );

it( 'should not display initial suggestions when input value is present', async () => {
const searchSuggestionsSpy = jest.fn( fetchFauxEntitySuggestions );
let searchResultElements;
//
// Render with an initial value an ensure that no initial suggestions
Expand All @@ -359,16 +342,15 @@ describe( 'Default search suggestions', () => {
act( () => {
render(
<LinkControl
fetchSearchSuggestions={ searchSuggestionsSpy }
showInitialSuggestions={ true }
showInitialSuggestions
value={ fauxEntitySuggestions[ 0 ] }
/>, container
);
} );

await eventLoopTick();

expect( searchSuggestionsSpy ).not.toHaveBeenCalled();
expect( mockFetchSearchSuggestions ).not.toHaveBeenCalled();

//
// Click the "Edit/Change" button and check initial suggestions are not
Expand All @@ -387,7 +369,7 @@ describe( 'Default search suggestions', () => {

expect( searchResultElements ).toHaveLength( 0 );

expect( searchSuggestionsSpy ).not.toHaveBeenCalled();
expect( mockFetchSearchSuggestions ).not.toHaveBeenCalled();

//
// Reset the search to empty and check the initial suggestions are now shown.
Expand All @@ -407,7 +389,7 @@ describe( 'Default search suggestions', () => {
// Ensure only called once as a guard against potential infinite
// re-render loop within `componentDidUpdate` calling `updateSuggestions`
// which has calls to `setState` within it.
expect( searchSuggestionsSpy ).toHaveBeenCalledTimes( 1 );
expect( mockFetchSearchSuggestions ).toHaveBeenCalledTimes( 1 );
} );
} );

Expand All @@ -418,18 +400,11 @@ describe( 'Selecting links', () => {
const LinkControlConsumer = () => {
const [ link ] = useState( selectedLink );

return (
<LinkControl
value={ link }
fetchSearchSuggestions={ fetchFauxEntitySuggestions }
/>
);
return <LinkControl value={ link } />;
};

act( () => {
render(
<LinkControlConsumer />, container
);
render( <LinkControlConsumer />, container );
} );

// TODO: select by aria role or visible text
Expand All @@ -453,15 +428,12 @@ describe( 'Selecting links', () => {
<LinkControl
value={ link }
onChange={ ( suggestion ) => setLink( suggestion ) }
fetchSearchSuggestions={ fetchFauxEntitySuggestions }
/>
);
};

act( () => {
render(
<LinkControlConsumer />, container
);
render( <LinkControlConsumer />, container );
} );

// Required in order to select the button below
Expand Down Expand Up @@ -499,7 +471,6 @@ describe( 'Selecting links', () => {
<LinkControl
value={ link }
onChange={ ( suggestion ) => setLink( suggestion ) }
fetchSearchSuggestions={ fetchFauxEntitySuggestions }
/>
);
};
Expand Down Expand Up @@ -559,7 +530,6 @@ describe( 'Selecting links', () => {
<LinkControl
value={ link }
onChange={ ( suggestion ) => setLink( suggestion ) }
fetchSearchSuggestions={ fetchFauxEntitySuggestions }
/>
);
};
Expand Down Expand Up @@ -644,18 +614,11 @@ describe( 'Addition Settings UI', () => {
const LinkControlConsumer = () => {
const [ link ] = useState( selectedLink );

return (
<LinkControl
value={ link }
fetchSearchSuggestions={ fetchFauxEntitySuggestions }
/>
);
return <LinkControl value={ link } />;
};

act( () => {
render(
<LinkControlConsumer />, container
);
render( <LinkControlConsumer />, container );
} );

const newTabSettingLabel = Array.from( container.querySelectorAll( 'label' ) ).find( ( label ) => label.innerHTML && label.innerHTML.includes( expectedSettingText ) );
Expand Down Expand Up @@ -689,16 +652,13 @@ describe( 'Addition Settings UI', () => {
return (
<LinkControl
value={ { ...link, newTab: false, noFollow: true } }
fetchSearchSuggestions={ fetchFauxEntitySuggestions }
settings={ customSettings }
/>
);
};

act( () => {
render(
<LinkControlConsumer />, container
);
render( <LinkControlConsumer />, container );
} );

// Grab the elements using user perceivable DOM queries
Expand Down

0 comments on commit 80e1a5a

Please sign in to comment.