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 Feb 11, 2019
1 parent 5b53bea commit b2f8ef9
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 63 deletions.
34 changes: 15 additions & 19 deletions packages/e2e-tests/specs/reusable-blocks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ import {
getEditedPostContent,
} from '@wordpress/e2e-test-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 @@ -40,11 +48,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 @@ -108,7 +111,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 @@ -117,7 +120,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 @@ -152,7 +155,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 @@ -175,7 +178,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 @@ -201,9 +204,7 @@ describe( 'Reusable Blocks', () => {
} );

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

// 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 @@ -217,7 +218,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 @@ -228,11 +229,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 @@ -257,7 +253,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
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 @@ -216,16 +216,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 @@ -302,20 +301,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
25 changes: 20 additions & 5 deletions packages/editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,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 @@ -413,7 +413,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 @@ -422,10 +422,15 @@ export const editor = flow( [
return getFlattenedBlocksWithoutAttributes( 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,
...getFlattenedBlocksWithoutAttributes( action.blocks ),
...getFlattenedBlocksWithoutAttributes( blocks ),
};
}

case 'UPDATE_BLOCK':
// Ignore updates if block isn't known
Expand Down Expand Up @@ -476,10 +481,15 @@ export const editor = flow( [
return getFlattenedBlockAttributes( 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,
...getFlattenedBlockAttributes( action.blocks ),
...getFlattenedBlockAttributes( blocks ),
};
}

case 'UPDATE_BLOCK':
// Ignore updates if block isn't known or there are no attribute changes.
Expand Down Expand Up @@ -552,10 +562,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 @@ -437,6 +438,7 @@ describe( 'effects', () => {

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

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

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

expect( result ).toEqual( [
setupEditorState( post, [], { title: 'A History of Pork' } ),
fetchReusableBlocks(),
] );
} );
} );
Expand Down
Loading

0 comments on commit b2f8ef9

Please sign in to comment.