Skip to content

Commit

Permalink
Patterns: Keep synced pattern when added via drag and drop
Browse files Browse the repository at this point in the history
  • Loading branch information
t-hamano committed Dec 10, 2023
1 parent 1783a4e commit b820542
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function BlockPattern( {
<InserterDraggableBlocks
isEnabled={ isDraggable }
blocks={ blocks }
isPattern={ !! pattern }
pattern={ pattern }
>
{ ( { draggable, onDragStart, onDragEnd } ) => (
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@
* WordPress dependencies
*/
import { Draggable } from '@wordpress/components';
import { serialize, store as blocksStore } from '@wordpress/blocks';
import {
createBlock,
serialize,
store as blocksStore,
} from '@wordpress/blocks';
import { useSelect } from '@wordpress/data';
/**
* Internal dependencies
*/
import BlockDraggableChip from '../block-draggable/draggable-chip';
import { PATTERN_TYPES } from '../inserter/block-patterns-tab/utils';

const InserterDraggableBlocks = ( {
isEnabled,
blocks,
icon,
children,
isPattern,
pattern,
} ) => {
const transferData = {
type: 'inserter',
Expand All @@ -36,13 +41,21 @@ const InserterDraggableBlocks = ( {
__experimentalTransferDataType="wp-blocks"
transferData={ transferData }
onDragStart={ ( event ) => {
event.dataTransfer.setData( 'text/html', serialize( blocks ) );
const parsedBlocks =
pattern?.type === PATTERN_TYPES.user &&
pattern?.syncStatus !== 'unsynced'
? [ createBlock( 'core/block', { ref: pattern.id } ) ]
: blocks;
event.dataTransfer.setData(
'text/html',
serialize( parsedBlocks )
);
} }
__experimentalDragComponent={
<BlockDraggableChip
count={ blocks.length }
icon={ icon || ( ! isPattern && blockTypeIcon ) }
isPattern={ isPattern }
icon={ icon || ( ! pattern && blockTypeIcon ) }
isPattern={ !! pattern }
/>
}
>
Expand Down
204 changes: 140 additions & 64 deletions test/e2e/specs/editor/various/inserting-blocks.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ test.use( {
test.describe( 'Inserting blocks (@firefox, @webkit)', () => {
test.afterAll( async ( { requestUtils } ) => {
await requestUtils.deleteAllPosts();
await requestUtils.deleteAllBlocks();
await requestUtils.deleteAllPatternCategories();
} );

test.afterEach( async ( { requestUtils } ) => {
await requestUtils.deleteAllBlocks();
await requestUtils.deleteAllPatternCategories();
} );

test( 'inserts blocks by dragging and dropping from the global inserter', async ( {
Expand Down Expand Up @@ -58,34 +65,16 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => {
const paragraphBoundingBox = await paragraphBlock.boundingBox();

await expect( insertingBlocksUtils.indicator ).toBeVisible();
// Expect the indicator to be below the paragraph block.
await expect
.poll( () =>
insertingBlocksUtils.indicator
.boundingBox()
.then( ( { y } ) => y )
)
.toBeGreaterThan( paragraphBoundingBox.y );
await insertingBlocksUtils.expectIndicatorBelowParagraph(
paragraphBoundingBox
);

await page.mouse.down();
// Call the move function twice to make sure the `dragOver` event is sent.
// @see https://github.com/microsoft/playwright/issues/17153
for ( let i = 0; i < 2; i += 1 ) {
await page.mouse.move(
// Hover on the right side of the block to avoid collapsing with the preview.
paragraphBoundingBox.x + paragraphBoundingBox.width - 1,
// Hover on the bottom of the paragraph block.
paragraphBoundingBox.y + paragraphBoundingBox.height - 1
);
}
// Expect the indicator to be below the paragraph block.
await expect
.poll( () =>
insertingBlocksUtils.indicator
.boundingBox()
.then( ( { y } ) => y )
)
.toBeGreaterThan( paragraphBoundingBox.y );

await insertingBlocksUtils.dragOver( paragraphBoundingBox );
await insertingBlocksUtils.expectIndicatorBelowParagraph(
paragraphBoundingBox
);

// Expect the draggable-chip to appear.
await expect( insertingBlocksUtils.draggableChip ).toBeVisible();
Expand Down Expand Up @@ -139,16 +128,8 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => {
const paragraphBoundingBox = await paragraphBlock.boundingBox();

await page.mouse.down();
// Call the move function twice to make sure the `dragOver` event is sent.
// @see https://github.com/microsoft/playwright/issues/17153
for ( let i = 0; i < 2; i += 1 ) {
await page.mouse.move(
// Hover on the right side of the block to avoid collapsing with the preview.
paragraphBoundingBox.x + paragraphBoundingBox.width - 1,
// Hover on the bottom of the paragraph block.
paragraphBoundingBox.y + paragraphBoundingBox.height - 1
);
}

await insertingBlocksUtils.dragOver( paragraphBoundingBox );

await expect( insertingBlocksUtils.indicator ).toBeVisible();
await expect( insertingBlocksUtils.draggableChip ).toBeVisible();
Expand Down Expand Up @@ -210,26 +191,13 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => {
const paragraphBoundingBox = await paragraphBlock.boundingBox();

await page.mouse.down();
// Call the move function twice to make sure the `dragOver` event is sent.
// @see https://github.com/microsoft/playwright/issues/17153
for ( let i = 0; i < 2; i += 1 ) {
await page.mouse.move(
// Hover on the right side of the block to avoid collapsing with the preview.
paragraphBoundingBox.x + paragraphBoundingBox.width - 1,
// Hover on the bottom of the paragraph block.
paragraphBoundingBox.y + paragraphBoundingBox.height - 1
);
}

await insertingBlocksUtils.dragOver( paragraphBoundingBox );

await expect( insertingBlocksUtils.indicator ).toBeVisible();
// Expect the indicator to be below the paragraph block.
await expect
.poll( () =>
insertingBlocksUtils.indicator
.boundingBox()
.then( ( { y } ) => y )
)
.toBeGreaterThan( paragraphBoundingBox.y );
await insertingBlocksUtils.expectIndicatorBelowParagraph(
paragraphBoundingBox
);

await expect( insertingBlocksUtils.draggableChip ).toBeVisible();

Expand All @@ -238,6 +206,103 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => {
expect( await editor.getEditedPostContent() ).toMatchSnapshot();
} );

test( 'inserts synced patterns by dragging and dropping from the global inserter', async ( {
admin,
page,
editor,
insertingBlocksUtils,
}, testInfo ) => {
testInfo.fixme(
testInfo.project.name === 'firefox',
'The clientX value is always 0 in firefox, see https://github.com/microsoft/playwright/issues/17761 for more info.'
);
const PATTERN_NAME = 'My synced pattern';

await admin.createNewPost();
await editor.switchToLegacyCanvas();

// We need a dummy block in place to display the drop indicator due to a bug.
// @see https://github.com/WordPress/gutenberg/issues/44064
await editor.insertBlock( {
name: 'core/paragraph',
attributes: { content: 'Dummy text' },
} );

const paragraphBlock = page.locator(
'[data-type="core/paragraph"] >> text=Dummy text'
);

// Create an unsynced pattern from the paragraph block.
await editor.insertBlock( {
name: 'core/paragraph',
attributes: { content: 'A useful paragraph to reuse' },
} );
await editor.showBlockToolbar();
await page
.getByRole( 'toolbar', { name: 'Block tools' } )
.getByRole( 'button', { name: 'Options' } )
.click();
await page.getByRole( 'menuitem', { name: 'Create pattern' } ).click();
const createPatternDialog = page.getByRole( 'dialog', {
name: 'Create pattern',
} );
await createPatternDialog
.getByRole( 'textbox', { name: 'Name' } )
.fill( PATTERN_NAME );
await createPatternDialog
.getByRole( 'checkbox', { name: 'Synced' } )
.setChecked( true );
await createPatternDialog
.getByRole( 'button', { name: 'Create' } )
.click();
const patternBlock = page.getByRole( 'document', {
name: 'Block: Pattern',
} );
await expect( patternBlock ).toBeFocused();

// Insert a synced pattern.
await page.click(
'role=region[name="Editor top bar"i] >> role=button[name="Toggle block inserter"i]'
);
await page.fill(
'role=region[name="Block Library"i] >> role=searchbox[name="Search for blocks and patterns"i]',
PATTERN_NAME
);
await page.hover(
`role=listbox[name="Block Patterns"i] >> role=option[name="${ PATTERN_NAME }"i]`
);

const paragraphBoundingBox = await paragraphBlock.boundingBox();

await page.mouse.down();

await insertingBlocksUtils.dragOver( paragraphBoundingBox );
await expect( insertingBlocksUtils.indicator ).toBeVisible();
await insertingBlocksUtils.expectIndicatorBelowParagraph(
paragraphBoundingBox
);
await expect( insertingBlocksUtils.draggableChip ).toBeVisible();

await page.mouse.up();

await expect.poll( editor.getBlocks ).toMatchObject( [
{
name: 'core/paragraph',
attributes: {
content: 'Dummy text',
},
},
{
name: 'core/block',
attributes: { ref: expect.any( Number ) },
},
{
name: 'core/block',
attributes: { ref: expect.any( Number ) },
},
] );
} );

test( 'cancels dragging patterns from the global inserter by pressing Escape', async ( {
admin,
page,
Expand Down Expand Up @@ -278,16 +343,8 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => {
const paragraphBoundingBox = await paragraphBlock.boundingBox();

await page.mouse.down();
// Call the move function twice to make sure the `dragOver` event is sent.
// @see https://github.com/microsoft/playwright/issues/17153
for ( let i = 0; i < 2; i += 1 ) {
await page.mouse.move(
// Hover on the right side of the block to avoid collapsing with the preview.
paragraphBoundingBox.x + paragraphBoundingBox.width - 1,
// Hover on the bottom of the paragraph block.
paragraphBoundingBox.y + paragraphBoundingBox.height - 1
);
}

await insertingBlocksUtils.dragOver( paragraphBoundingBox );

await expect( insertingBlocksUtils.indicator ).toBeVisible();
await expect( insertingBlocksUtils.draggableChip ).toBeVisible();
Expand Down Expand Up @@ -388,4 +445,23 @@ class InsertingBlocksUtils {
'data-testid=block-draggable-chip >> visible=true'
);
}
async dragOver( boundingBox ) {
// Call the move function twice to make sure the `dragOver` event is sent.
// @see https://github.com/microsoft/playwright/issues/17153
for ( let i = 0; i < 2; i += 1 ) {
await this.page.mouse.move(
// Hover on the right side of the block to avoid collapsing with the preview.
boundingBox.x + boundingBox.width - 1,
// Hover on the bottom of the paragraph block.
boundingBox.y + boundingBox.height - 1
);
}
}

async expectIndicatorBelowParagraph( paragraphBoundingBox ) {
// Expect the indicator to be below the paragraph block.
await expect
.poll( () => this.indicator.boundingBox().then( ( { y } ) => y ) )
.toBeGreaterThan( paragraphBoundingBox.y );
}
}

0 comments on commit b820542

Please sign in to comment.