Skip to content

Commit

Permalink
Reusable Blocks: Fix failing E2E tests
Browse files Browse the repository at this point in the history
  • Loading branch information
noisysocks committed Nov 12, 2018
1 parent 5a59492 commit 98227ef
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 62 deletions.
13 changes: 1 addition & 12 deletions packages/editor/src/hooks/default-autocompleters.js
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -17,23 +16,13 @@ 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.
completers = defaultAutocompleters.map( clone );
// 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;
Expand Down
8 changes: 6 additions & 2 deletions packages/editor/src/store/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
resetBlocks,
setTemplateValidity,
insertDefaultBlock,
__experimentalFetchReusableBlocks as fetchReusableBlocksAction,
} from './actions';
import {
getBlock,
Expand All @@ -45,7 +46,6 @@ import {
deleteReusableBlocks,
convertBlockToReusable,
convertBlockToStatic,
receiveReusableBlocks,
} from './effects/reusable-blocks';
import {
requestPostUpdate,
Expand Down Expand Up @@ -232,6 +232,11 @@ export default {
//
// See: https://github.com/WordPress/gutenberg/pull/9403
validateBlocksToTemplate( setupAction, store ),

// Fetch reusable blocks when the editor initialises. This ensures that they
// appear in the block autocompleter. This is temporary until reusable blocks
// are fetched using a select() resolver.
fetchReusableBlocksAction(),
] );
},
RESET_BLOCKS: [
Expand All @@ -254,7 +259,6 @@ export default {
DELETE_REUSABLE_BLOCK: ( action, store ) => {
deleteReusableBlocks( action, store );
},
RECEIVE_REUSABLE_BLOCKS: receiveReusableBlocks,
CONVERT_BLOCK_TO_STATIC: convertBlockToStatic,
CONVERT_BLOCK_TO_REUSABLE: convertBlockToReusable,
REMOVE_BLOCKS: [
Expand Down
10 changes: 0 additions & 10 deletions packages/editor/src/store/effects/reusable-blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,16 +212,6 @@ export const deleteReusableBlocks = async ( action, store ) => {
}
};

/**
* Receive Reusable Blocks Effect Handler.
*
* @param {Object} action action object.
* @return {Object} receive blocks action
*/
export const receiveReusableBlocks = ( action ) => {
return receiveBlocks( map( action.results, 'parsedBlock' ) );
};

/**
* Convert a reusable block to a static block effect handler
*
Expand Down
15 changes: 0 additions & 15 deletions packages/editor/src/store/effects/test/reusable-blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
import {
fetchReusableBlocks,
saveReusableBlocks,
receiveReusableBlocks,
deleteReusableBlocks,
convertBlockToStatic,
convertBlockToReusable,
Expand Down Expand Up @@ -262,20 +261,6 @@ describe( 'reusable blocks effects', () => {
} );
} );

describe( 'receiveReusableBlocks', () => {
it( 'should receive parsed blocks', () => {
const action = receiveReusableBlocksAction( [
{
parsedBlock: { clientId: 'broccoli' },
},
] );

expect( receiveReusableBlocks( action ) ).toEqual( receiveBlocks( [
{ clientId: 'broccoli' },
] ) );
} );
} );

describe( 'deleteReusableBlocks', () => {
it( 'should delete a reusable block', async () => {
const deletePromise = Promise.resolve( {} );
Expand Down
18 changes: 14 additions & 4 deletions packages/editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ export const editor = flow( [
// Track undo history, starting at editor initialization.
withHistory( {
resetTypes: [ 'SETUP_EDITOR_STATE' ],
ignoreTypes: [ 'RECEIVE_BLOCKS', 'RESET_POST', 'UPDATE_POST' ],
ignoreTypes: [ 'RECEIVE_BLOCKS', 'RECEIVE_REUSABLE_BLOCKS', 'RESET_POST', 'UPDATE_POST' ],
shouldOverwriteState,
} ),
] )( {
Expand Down Expand Up @@ -284,7 +284,7 @@ export const editor = flow( [
// editor initialization firing post reset as an effect.
withChangeDetection( {
resetTypes: [ 'SETUP_EDITOR_STATE', 'REQUEST_POST_UPDATE_START' ],
ignoreTypes: [ 'RECEIVE_BLOCKS', 'RESET_POST', 'UPDATE_POST' ],
ignoreTypes: [ 'RECEIVE_BLOCKS', 'RECEIVE_REUSABLE_BLOCKS', 'RESET_POST', 'UPDATE_POST' ],
} ),
] )( {
byClientId( state = {}, action ) {
Expand All @@ -294,10 +294,15 @@ export const editor = flow( [
return getFlattenedBlocks( action.blocks );

case 'RECEIVE_BLOCKS':
case 'RECEIVE_REUSABLE_BLOCKS': {
const blocks = action.type === 'RECEIVE_BLOCKS' ?
action.blocks :
action.results.map( ( result ) => result.parsedBlock );
return {
...state,
...getFlattenedBlocks( action.blocks ),
...getFlattenedBlocks( blocks ),
};
}

case 'UPDATE_BLOCK_ATTRIBUTES':
// Ignore updates if block isn't known
Expand Down Expand Up @@ -397,10 +402,15 @@ export const editor = flow( [
return mapBlockOrder( action.blocks );

case 'RECEIVE_BLOCKS':
case 'RECEIVE_REUSABLE_BLOCKS': {
const blocks = action.type === 'RECEIVE_BLOCKS' ?
action.blocks :
action.results.map( ( result ) => result.parsedBlock );
return {
...state,
...omit( mapBlockOrder( action.blocks ), '' ),
...omit( mapBlockOrder( blocks ), '' ),
};
}

case 'INSERT_BLOCKS': {
const { rootClientId = '', blocks } = action;
Expand Down
4 changes: 4 additions & 0 deletions packages/editor/src/store/test/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import actions, {
resetBlocks,
selectBlock,
setTemplateValidity,
__experimentalFetchReusableBlocks as fetchReusableBlocks,
} from '../actions';
import effects, { validateBlocksToTemplate } from '../effects';
import { SAVE_POST_NOTICE_ID } from '../effects/posts';
Expand Down Expand Up @@ -420,6 +421,7 @@ describe( 'effects', () => {

expect( result ).toEqual( [
setupEditorState( post, [], {} ),
fetchReusableBlocks(),
] );
} );

Expand Down Expand Up @@ -450,6 +452,7 @@ describe( 'effects', () => {
expect( result[ 0 ].blocks ).toHaveLength( 1 );
expect( result ).toEqual( [
setupEditorState( post, result[ 0 ].blocks, {} ),
fetchReusableBlocks(),
] );
} );

Expand Down Expand Up @@ -478,6 +481,7 @@ describe( 'effects', () => {

expect( result ).toEqual( [
setupEditorState( post, [], { title: 'A History of Pork' } ),
fetchReusableBlocks(),
] );
} );
} );
Expand Down
70 changes: 70 additions & 0 deletions packages/editor/src/store/test/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,76 @@ describe( 'state', () => {

expect( state.present.blocks.byClientId ).toBe( state.present.blocks.byClientId );
} );

it( 'should receive blocks', () => {
const original = deepFreeze( editor( undefined, {
type: 'RESET_BLOCKS',
blocks: [ {
clientId: 'block1',
attributes: {},
innerBlocks: [],
} ],
} ) );
const state = editor( original, {
type: 'RECEIVE_BLOCKS',
blocks: [
{
clientId: 'block2',
attributes: {},
innerBlocks: [],
},
{
clientId: 'block3',
attributes: {},
innerBlocks: [],
},
],
} );

expect( state.present.blocks.byClientId ).toEqual( {
block1: { clientId: 'block1', attributes: {} },
block2: { clientId: 'block2', attributes: {} },
block3: { clientId: 'block3', attributes: {} },
} );
} );

it( 'should receive reusable blocks', () => {
const original = deepFreeze( editor( undefined, {
type: 'RESET_BLOCKS',
blocks: [ {
clientId: 'block1',
attributes: {},
innerBlocks: [],
} ],
} ) );
const state = editor( original, {
type: 'RECEIVE_REUSABLE_BLOCKS',
results: [
{
reusableBlock: {},
parsedBlock: {
clientId: 'block2',
attributes: {},
innerBlocks: [],
},
},
{
reusableBlock: {},
parsedBlock: {
clientId: 'block3',
attributes: {},
innerBlocks: [],
},
},
],
} );

expect( state.present.blocks.byClientId ).toEqual( {
block1: { clientId: 'block1', attributes: {} },
block2: { clientId: 'block2', attributes: {} },
block3: { clientId: 'block3', attributes: {} },
} );
} );
} );
} );

Expand Down
34 changes: 15 additions & 19 deletions test/e2e/specs/reusable-blocks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ import {
META_KEY,
} from '../support/utils';

async function waitForAndInsertBlock( blockLabel ) {
// Since we are working with new posts, we need to wait for the inserter to
// finish fetching reusable blocks before clicking on the desired block.
await searchForBlock( blockLabel );
await page.waitForSelector( `button[aria-label="${ blockLabel }"]` );
await page.click( `button[aria-label="${ blockLabel }"]` );
}

function waitForAndAcceptDialog() {
return new Promise( ( resolve ) => {
page.once( 'dialog', () => resolve() );
Expand Down Expand Up @@ -41,11 +49,6 @@ describe( 'Reusable Blocks', () => {
'//*[contains(@class, "components-notice") and contains(@class, "is-success")]/*[text()="Block created."]'
);

// Select all of the text in the title field by triple-clicking on it. We
// triple-click because, on Mac, Mod+A doesn't work. This step can be removed
// when https://github.com/WordPress/gutenberg/issues/7972 is fixed
await page.click( '.reusable-block-edit-panel__title', { clickCount: 3 } );

// Give the reusable block a title
await page.keyboard.type( 'Greeting block' );

Expand Down Expand Up @@ -109,7 +112,7 @@ describe( 'Reusable Blocks', () => {

it( 'can be inserted and edited', async () => {
// Insert the reusable block we created above
await insertBlock( 'Greeting block' );
await waitForAndInsertBlock( 'Greeting block' );

// Put the reusable block in edit mode
const [ editButton ] = await page.$x( '//button[text()="Edit"]' );
Expand All @@ -118,7 +121,7 @@ describe( 'Reusable Blocks', () => {
// Change the block's title
await page.keyboard.type( 'Surprised greeting block' );

// Tab three times to navigate to the block's content
// Tab two times to navigate to the block's content
await page.keyboard.press( 'Tab' );
await page.keyboard.press( 'Tab' );

Expand Down Expand Up @@ -153,7 +156,7 @@ describe( 'Reusable Blocks', () => {

it( 'can be converted to a regular block', async () => {
// Insert the reusable block we edited above
await insertBlock( 'Surprised greeting block' );
await waitForAndInsertBlock( 'Surprised greeting block' );

// Convert block to a regular block
await page.click( 'button[aria-label="More options"]' );
Expand All @@ -176,7 +179,7 @@ describe( 'Reusable Blocks', () => {

it( 'can be deleted', async () => {
// Insert the reusable block we edited above
await insertBlock( 'Surprised greeting block' );
await waitForAndInsertBlock( 'Surprised greeting block' );

// Delete the block and accept the confirmation dialog
await page.click( 'button[aria-label="More options"]' );
Expand All @@ -197,9 +200,7 @@ describe( 'Reusable Blocks', () => {
} );

it( 'can be created from multiselection', async () => {
await newPost();

// Insert a Two paragraphs block
// Insert two paragraph blocks
await insertBlock( 'Paragraph' );
await page.keyboard.type( 'Hello there!' );
await page.keyboard.press( 'Enter' );
Expand All @@ -213,7 +214,7 @@ describe( 'Reusable Blocks', () => {
await page.mouse.move( 200, 300, { steps: 10 } );
await page.mouse.move( 250, 350, { steps: 10 } );

// Convert block to a reusable block
// Convert blocks to a reusable block
await page.waitForSelector( 'button[aria-label="More options"]' );
await page.click( 'button[aria-label="More options"]' );
const convertButton = await page.waitForXPath( '//button[text()="Add to Reusable Blocks"]' );
Expand All @@ -224,11 +225,6 @@ describe( 'Reusable Blocks', () => {
'//*[contains(@class, "components-notice") and contains(@class, "is-success")]/*[text()="Block created."]'
);

// Select all of the text in the title field by triple-clicking on it. We
// triple-click because, on Mac, Mod+A doesn't work. This step can be removed
// when https://github.com/WordPress/gutenberg/issues/7972 is fixed
await page.click( '.reusable-block-edit-panel__title', { clickCount: 3 } );

// Give the reusable block a title
await page.keyboard.type( 'Multi-selection reusable block' );

Expand All @@ -253,7 +249,7 @@ describe( 'Reusable Blocks', () => {

it( 'multi-selection reusable block can be converted back to regular blocks', async () => {
// Insert the reusable block we edited above
await insertBlock( 'Multi-selection reusable block' );
await waitForAndInsertBlock( 'Multi-selection reusable block' );

// Convert block to a regular block
await page.click( 'button[aria-label="More options"]' );
Expand Down

0 comments on commit 98227ef

Please sign in to comment.