Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block Editor: Include reusable blocks in announced inserter search results #22279

Merged
merged 5 commits into from
May 12, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 4 additions & 13 deletions packages/block-editor/src/components/inserter/block-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const getBlockNamespace = ( item ) => item.name.split( '/' )[ 0 ];

const MAX_SUGGESTED_ITEMS = 9;

function InserterBlockList( {
export function InserterBlockList( {
rootClientId,
onInsert,
onHover,
Expand Down Expand Up @@ -168,22 +168,13 @@ function InserterBlockList( {

// Announce search results on change
useEffect( () => {
const resultCount = Object.keys( itemsPerCategory ).reduce(
( accumulator, currentCategorySlug ) => {
return (
accumulator + itemsPerCategory[ currentCategorySlug ].length
);
},
0
);

const resultsFoundMessage = sprintf(
/* translators: %d: number of results. */
_n( '%d result found.', '%d results found.', resultCount ),
resultCount
_n( '%d result found.', '%d results found.', filteredItems.length ),
filteredItems.length
);
debouncedSpeak( resultsFoundMessage );
}, [ itemsPerCategory, debouncedSpeak ] );
}, [ filteredItems.length, debouncedSpeak ] );
aduth marked this conversation as resolved.
Show resolved Hide resolved

const hasItems = ! isEmpty( filteredItems );
const hasChildItems = childItems.length > 0;
Expand Down
75 changes: 54 additions & 21 deletions packages/block-editor/src/components/inserter/test/block-list.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,37 @@
/**
* External dependencies
*/
import TestUtils, { act } from 'react-dom/test-utils';
import ReactDOM from 'react-dom';
import { render, fireEvent } from '@testing-library/react';

/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import InserterBlockList from '../block-list';
import useSelect from '../../../../../data/src/components/use-select';
import { InserterBlockList } from '../block-list';
import items, { categories, collections } from './fixtures';

jest.mock( '../../../../../data/src/components/use-select', () => {
// This allows us to tweaak the returned value on each test
jest.mock( '@wordpress/data/src/components/use-select', () => {
// This allows us to tweak the returned value on each test
const mock = jest.fn();
return mock;
} );

jest.mock( '../../../../../data/src/components/use-dispatch', () => {
jest.mock( '@wordpress/data/src/components/use-dispatch', () => {
return {
useDispatch: () => ( {} ),
};
} );

const getWrapperForProps = ( propOverrides ) => {
let wrapper;
act( () => {
wrapper = TestUtils.renderIntoDocument(
<InserterBlockList { ...propOverrides } />
);
} );

return wrapper;
};
const speak = jest.fn();

const initializeMenuDefaultStateAndReturnElement = ( propOverrides ) => {
const wrapper = getWrapperForProps( propOverrides );
// eslint-disable-next-line react/no-find-dom-node
return ReactDOM.findDOMNode( wrapper );
return render(
<InserterBlockList debouncedSpeak={ speak } { ...propOverrides } />
).container;
};

const initializeAllClosedMenuStateAndReturnElement = ( propOverrides ) => {
Expand All @@ -46,7 +40,7 @@ const initializeAllClosedMenuStateAndReturnElement = ( propOverrides ) => {
'.components-panel__body.is-opened button.components-panel__body-toggle'
);
activeTabs.forEach( ( tab ) => {
TestUtils.Simulate.click( tab );
fireEvent.click( tab );
} );
return element;
};
Expand All @@ -67,6 +61,8 @@ const assertNoResultsMessageNotToBePresent = ( element ) => {

describe( 'InserterMenu', () => {
beforeEach( () => {
speak.mockClear();

useSelect.mockImplementation( () => ( {
categories,
collections,
Expand Down Expand Up @@ -192,16 +188,53 @@ describe( 'InserterMenu', () => {
expect( matchingCategories ).toHaveLength( 3 );
expect( matchingCategories[ 0 ].textContent ).toBe( 'Common blocks' );
expect( matchingCategories[ 1 ].textContent ).toBe( 'Embeds' );
expect( matchingCategories[ 2 ].textContent ).toBe( 'Core' ); // "Core" namespace collection

const blocks = element.querySelectorAll(
'.block-editor-block-types-list__item-title'
);

// There are five buttons present for 3 total distinct results. The
// additional two account for the collection results (repeated).
expect( blocks ).toHaveLength( 5 );
expect( speak ).toHaveBeenCalledWith( '3 results found.' );

// Default block results.
expect( blocks[ 0 ].textContent ).toBe( 'Text' );
expect( blocks[ 1 ].textContent ).toBe( 'Advanced Text' );
expect( blocks[ 2 ].textContent ).toBe( 'A Text Embed' );

// Collection results.
expect( blocks[ 3 ].textContent ).toBe( 'Text' );
expect( blocks[ 4 ].textContent ).toBe( 'Advanced Text' );

assertNoResultsMessageNotToBePresent( element );
} );

it( 'should allow searching for reusable blocks by title', () => {
const element = initializeMenuDefaultStateAndReturnElement( {
filterValue: 'my reusable',
} );

const matchingCategories = element.querySelectorAll(
'.block-editor-inserter__panel-title'
);

expect( matchingCategories ).toHaveLength( 2 );
expect( matchingCategories[ 0 ].textContent ).toBe( 'Core' ); // "Core" namespace collection
expect( matchingCategories[ 1 ].textContent ).toBe( 'Reusable' );

const blocks = element.querySelectorAll(
'.block-editor-block-types-list__item-title'
);

// There are two buttons present for 1 total distinct result. The
// additional one accounts for the collection result (repeated).
expect( blocks ).toHaveLength( 2 );
expect( speak ).toHaveBeenCalledWith( '1 result found.' );
expect( blocks[ 0 ].textContent ).toBe( 'My reusable block' );
expect( blocks[ 1 ].textContent ).toBe( 'My reusable block' );

assertNoResultsMessageNotToBePresent( element );
} );

Expand Down