From e209cfb77469b0e022198f75ab1fd641f98b229a Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Wed, 17 Apr 2019 07:34:31 -0400 Subject: [PATCH] Editor: Trigger reusable blocks autocomplete when options generated (#14915) --- .../src/components/autocompleters/block.js | 28 ++++++++++++++++++- .../components/autocompleters/test/block.js | 22 ++++++++++++++- .../src/hooks/default-autocompleters.js | 13 +-------- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/packages/editor/src/components/autocompleters/block.js b/packages/editor/src/components/autocompleters/block.js index 746928ea7752e..70860643ae096 100644 --- a/packages/editor/src/components/autocompleters/block.js +++ b/packages/editor/src/components/autocompleters/block.js @@ -1,7 +1,12 @@ +/** + * External dependencies + */ +import { once } from 'lodash'; + /** * WordPress dependencies */ -import { select } from '@wordpress/data'; +import { select, dispatch } from '@wordpress/data'; import { createBlock } from '@wordpress/blocks'; import { BlockIcon } from '@wordpress/block-editor'; @@ -41,6 +46,25 @@ function defaultGetSelectedBlockName() { return selectedBlockClientId ? getBlockName( selectedBlockClientId ) : null; } +/** + * Triggers a fetch of reusable blocks, once. + * + * TODO: Reusable blocks fetching should be reimplemented as a core-data entity + * resolver, not relying on `core/editor` (see #7119). The implementation here + * is imperfect in that the options result will not await the completion of the + * fetch request and thus will not include any reusable blocks. This has always + * been true, but relied upon the fact the user would be delayed in typing an + * autocompleter search query. Once implemented using resolvers, the status of + * this request could be subscribed to as part of a promised return value using + * the result of `hasFinishedResolution`. There is currently reliable way to + * determine that a reusable blocks fetch request has completed. + * + * @return {Promise} Promise resolving once reusable blocks fetched. + */ +const fetchReusableBlocks = once( () => { + dispatch( 'core/editor' ).__experimentalFetchReusableBlocks(); +} ); + /** * Creates a blocks repeater for replacing the current block with a selected block type. * @@ -57,6 +81,8 @@ export function createBlockCompleter( { className: 'editor-autocompleters__block', triggerPrefix: '/', options() { + fetchReusableBlocks(); + const selectedBlockName = getSelectedBlockName(); return getInserterItems( getBlockInsertionParentClientId() ).filter( // Avoid offering to replace the current block with a block of the same type. diff --git a/packages/editor/src/components/autocompleters/test/block.js b/packages/editor/src/components/autocompleters/test/block.js index 8b853cd693173..71582b3e33ba8 100644 --- a/packages/editor/src/components/autocompleters/test/block.js +++ b/packages/editor/src/components/autocompleters/test/block.js @@ -7,9 +7,29 @@ import { shallow } from 'enzyme'; * Internal dependencies */ import blockCompleter, { createBlockCompleter } from '../block'; +import '../../../'; describe( 'block', () => { - it( 'should retrieve block options for current insertion point', () => { + let originalFetch; + beforeEach( () => { + originalFetch = window.fetch; + window.fetch = ( url ) => { + if ( ! /\/wp\/v2\/types\/wp_block(\?|$)/.test( url ) ) { + throw new Error( 'Unhandled fetch ' + url ); + } + + return Promise.resolve( { + status: 200, + json: () => Promise.resolve( [] ), + } ); + }; + } ); + + afterEach( () => { + window.fetch = originalFetch; + } ); + + it( 'should retrieve block options for current insertion point', async () => { const expectedOptions = [ {}, {}, {} ]; const mockGetBlockInsertionParentClientId = jest.fn( () => 'expected-insertion-point' ); const mockGetInserterItems = jest.fn( () => expectedOptions ); diff --git a/packages/editor/src/hooks/default-autocompleters.js b/packages/editor/src/hooks/default-autocompleters.js index 6ab43ed47d6ab..b80bbc485857e 100644 --- a/packages/editor/src/hooks/default-autocompleters.js +++ b/packages/editor/src/hooks/default-autocompleters.js @@ -1,14 +1,13 @@ /** * External dependencies */ -import { clone, once } from 'lodash'; +import { clone } from 'lodash'; /** * WordPress dependencies */ import { addFilter } from '@wordpress/hooks'; import { getDefaultBlockName } from '@wordpress/blocks'; -import { dispatch } from '@wordpress/data'; /** * Internal dependencies @@ -17,8 +16,6 @@ import { blockAutocompleter, userAutocompleter } from '../components'; const defaultAutocompleters = [ userAutocompleter ]; -const fetchReusableBlocks = once( () => dispatch( 'core/editor' ).__experimentalFetchReusableBlocks() ); - function setDefaultCompleters( completers, blockName ) { if ( ! completers ) { // Provide copies so filters may directly modify them. @@ -26,14 +23,6 @@ function setDefaultCompleters( completers, blockName ) { // Add blocks autocompleter for Paragraph block if ( blockName === getDefaultBlockName() ) { completers.push( clone( blockAutocompleter ) ); - - /* - * NOTE: This is a hack to help ensure reusable blocks are loaded - * so they may be included in the block completer. It can be removed - * once we have a way for completers to Promise options while - * store-based data dependencies are being resolved. - */ - fetchReusableBlocks(); } } return completers;