Skip to content

Commit

Permalink
Fix e2e test and add the pageUtils.dragFiles e2e util
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin940726 committed Jul 29, 2022
1 parent 50c6d11 commit 2a95bfc
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 36 deletions.
17 changes: 16 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
"@types/highlight-words-core": "1.2.1",
"@types/istanbul-lib-report": "3.0.0",
"@types/lodash": "4.14.172",
"@types/mime": "2.0.3",
"@types/npm-package-arg": "6.1.1",
"@types/prettier": "2.4.4",
"@types/qs": "6.9.7",
Expand Down
18 changes: 12 additions & 6 deletions packages/block-library/src/paragraph/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { useRef } from '@wordpress/element';
import { useState } from '@wordpress/element';
import { __, _x, isRTL } from '@wordpress/i18n';
import {
ToolbarButton,
Expand Down Expand Up @@ -62,9 +62,15 @@ function ParagraphBlock( {
} ) {
const { align, content, direction, dropCap, placeholder } = attributes;
const isDropCapFeatureEnabled = useSetting( 'typography.dropCap' );
const ref = useRef();
const [ paragraphElement, setParagraphElement ] = useState( null );
const refCallback = ( element ) => {
setParagraphElement( element );
};
const blockProps = useBlockProps( {
ref: useMergeRefs( [ useOnEnter( { clientId, content } ), ref ] ),
ref: useMergeRefs( [
useOnEnter( { clientId, content } ),
refCallback,
] ),
className: classnames( {
'has-drop-cap': dropCap,
[ `has-text-align-${ align }` ]: align,
Expand Down Expand Up @@ -119,7 +125,7 @@ function ParagraphBlock( {
) }
{ ! content && (
<Popover
anchorRef={ ref.current }
anchorRef={ paragraphElement }
animate={ false }
position="top right left"
focusOnMount={ false }
Expand All @@ -129,8 +135,8 @@ function ParagraphBlock( {
<DropZone
style={ {
// TODO: Ideally we should observe the size of the paragraph block.
width: ref.current?.offsetWidth,
height: ref.current?.offsetHeight,
width: paragraphElement?.offsetWidth,
height: paragraphElement?.offsetHeight,
} }
onFilesDrop={ ( files ) => {
if ( files.length === 1 ) {
Expand Down
3 changes: 2 additions & 1 deletion packages/e2e-test-utils-playwright/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"@wordpress/keycodes": "file:../keycodes",
"@wordpress/url": "file:../url",
"form-data": "^4.0.0",
"lodash": "^4.17.21"
"lodash": "^4.17.21",
"mime": "^3.0.0"
},
"peerDependencies": {
"@playwright/test": ">=1"
Expand Down
131 changes: 131 additions & 0 deletions packages/e2e-test-utils-playwright/src/page-utils/drag-files.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/**
* External dependencies
*/
import { readFile } from 'fs/promises';
import { basename } from 'path';
import { getType } from 'mime';

/**
* Internal dependencies
*/
import type { PageUtils } from './index';

type FileObject = {
name: string;
mimeType?: string;
buffer: Buffer;
};

/**
* Simulate dragging files from outside the current page.
*
* @param this
* @param files The files to be dragged.
* @return The methods of the drag operation.
*/
async function dragFiles(
this: PageUtils,
files: string | string[] | FileObject | FileObject[]
) {
const filesList = Array.isArray( files ) ? files : [ files ];
const fileObjects = await Promise.all(
filesList.map( async ( filePathOrObject ) => {
if ( typeof filePathOrObject !== 'string' ) {
return {
name: filePathOrObject.name,
mimeType:
filePathOrObject.mimeType ||
getType( filePathOrObject.name ),
base64: filePathOrObject.buffer.toString( 'base64' ),
};
}
const base64 = await readFile( filePathOrObject, 'base64' );
const name = basename( filePathOrObject );
return {
name,
mimeType: getType( filePathOrObject ),
base64,
};
} )
);

const dataTransfer = await this.page.evaluateHandle(
async ( _fileObjects ) => {
const dt = new DataTransfer();
const fileInstances = await Promise.all(
_fileObjects.map( async ( fileObject ) => {
const blob = await fetch(
`data:${ fileObject.mimeType };base64,${ fileObject.base64 }`
).then( ( res ) => res.blob() );
return new File( [ blob ], fileObject.name, {
type: fileObject.mimeType ?? undefined,
} );
} )
);

fileInstances.forEach( ( file ) => {
dt.items.add( file );
} );

return dt;
},
fileObjects
);

// Simulate dragging over the document.
await this.page.dispatchEvent( 'html', 'dragenter', { dataTransfer } );

const position = {
x: 0,
y: 0,
};

const getCurrentTopMostElement = async () => {
const elementFromPosition = await this.page.evaluateHandle(
( point ) => {
const element = document.elementFromPoint( point.x, point.y );
return element;
},
position
);

return elementFromPosition.asElement();
};

return {
/**
* Move the cursor and drag the files to the specified position.
*
* @param x The X coordinate.
* @param y The Y coordinate.
*/
dragTo: async ( x: number, y: number ) => {
position.x = x;
position.y = y;

const elementHandle = await getCurrentTopMostElement();

if ( ! elementHandle ) {
return;
}

await elementHandle.dispatchEvent( 'dragenter', { dataTransfer } );
},
/**
* Drop the files at the current position.
*/
drop: async () => {
const elementHandle = await getCurrentTopMostElement();

if ( ! elementHandle ) {
throw new Error(
`No element at position (${ position.x }, ${ position.y }) to drop on`
);
}

await elementHandle.dispatchEvent( 'drop', { dataTransfer } );
},
};
}

export { dragFiles };
2 changes: 2 additions & 0 deletions packages/e2e-test-utils-playwright/src/page-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { Browser, Page, BrowserContext } from '@playwright/test';
/**
* Internal dependencies
*/
import { dragFiles } from './drag-files';
import { isCurrentURL } from './is-current-url';
import {
setClipboardData,
Expand All @@ -29,6 +30,7 @@ class PageUtils {
this.browser = this.context.browser()!;
}

dragFiles = dragFiles.bind( this );
isCurrentURL = isCurrentURL.bind( this );
pressKeyTimes = pressKeyTimes.bind( this );
pressKeyWithModifier = pressKeyWithModifier.bind( this );
Expand Down
45 changes: 17 additions & 28 deletions test/e2e/specs/editor/blocks/paragraph.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* External dependencies
*/
const path = require( 'path' );
const fs = require( 'fs/promises' );

/**
* WordPress dependencies
Expand Down Expand Up @@ -46,56 +45,46 @@ test.describe( 'Paragraph', () => {
expect( firstBlockTagName ).toBe( 'P' );
} );

test( 'should allow dropping an image on en empty paragraph block', async ( {
test.only( 'should allow dropping an image on en empty paragraph block', async ( {
editor,
page,
pageUtils,
} ) => {
await editor.insertBlock( { name: 'core/paragraph' } );
const emptyParagraphBlock = page.locator(
'[data-type="core/paragraph"]'
);

const testImageName = '10x10_e2e_test_image_z9T8jK.png';
const testImagePath = path.join(
__dirname,
'../../../assets/10x10_e2e_test_image_z9T8jK.png'
);
const testImage = await fs.readFile( testImagePath, 'base64' );
const dataTransfer = await page.evaluateHandle(
async ( [ base64 ] ) => {
const blobResponse = await window.fetch(
`data:image/png;base64,${ base64 }`
);
const blob = await blobResponse.blob();
const file = new window.File( [ blob ], 'test-image.png', {
type: 'image/png',
} );
const dt = new window.DataTransfer();
dt.items.add( file );
return dt;
},
[ testImage ]
'../../../assets',
testImageName
);

const dropZone = emptyParagraphBlock.locator(
'[data-is-drop-zone="true"]'
);
// Simulate dragging from outside the browser.
await page.dispatchEvent( 'html', 'dragenter', { dataTransfer } );
await dropZone.dispatchEvent( 'dragenter', { dataTransfer } );
const { dragTo, drop } = await pageUtils.dragFiles( testImagePath );

const { x, y, width, height } = await emptyParagraphBlock.boundingBox();
const centerPosition = {
x: x + width / 2,
y: y + height / 2,
};

await dragTo( centerPosition.x, centerPosition.y );

await expect(
emptyParagraphBlock.locator( 'text="Drop files to upload"' )
page.locator( 'text="Drop files to upload"' )
).toBeVisible();

await dropZone.dispatchEvent( 'drop', { dataTransfer } );
await drop();

const imageBlock = page.locator(
'role=document[name="Block: Image"i]'
);
await expect( imageBlock ).toBeVisible();
await expect( imageBlock.locator( 'role=img' ) ).toHaveAttribute(
'src',
/test-image\.png$/
new RegExp( testImageName.replace( '.', '\\.' ) )
);
} );
} );

0 comments on commit 2a95bfc

Please sign in to comment.