From 5ee2d540205c13296f06d3ca7f8490678843f4a1 Mon Sep 17 00:00:00 2001 From: Kai Hao Date: Fri, 30 Sep 2022 15:30:14 +0800 Subject: [PATCH 1/4] Add e2e tests for DnD in the inserter --- .github/workflows/end2end-test-playwright.yml | 6 +- .../components/inserter-list-item/style.scss | 2 + test/e2e/playwright.config.ts | 25 ++ ...ng-from-the-global-inserter-1-chromium.txt | 11 + ...ping-from-the-global-inserter-1-webkit.txt | 11 + .../editor/various/inserting-blocks.spec.js | 300 ++++++++++++++++++ 6 files changed, 352 insertions(+), 3 deletions(-) create mode 100644 test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-chromium.txt create mode 100644 test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-webkit.txt create mode 100644 test/e2e/specs/editor/various/inserting-blocks.spec.js diff --git a/.github/workflows/end2end-test-playwright.yml b/.github/workflows/end2end-test-playwright.yml index c65f56b824c91..7a92e57f65563 100644 --- a/.github/workflows/end2end-test-playwright.yml +++ b/.github/workflows/end2end-test-playwright.yml @@ -39,7 +39,7 @@ jobs: - name: Install Playwright dependencies run: | - npx playwright install chromium --with-deps + npx playwright install chromium firefox webkit --with-deps - name: Install WordPress and start the server run: | @@ -47,14 +47,14 @@ jobs: - name: Run the tests run: | - npm run test:e2e:playwright + xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test:e2e:playwright - name: Archive debug artifacts (screenshots, traces) uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 if: always() with: name: failures-artifacts - path: artifacts + path: artifacts/test-results if-no-files-found: ignore - name: Archive flaky tests report diff --git a/packages/block-editor/src/components/inserter-list-item/style.scss b/packages/block-editor/src/components/inserter-list-item/style.scss index 981d470a81d6a..b3078adb519f1 100644 --- a/packages/block-editor/src/components/inserter-list-item/style.scss +++ b/packages/block-editor/src/components/inserter-list-item/style.scss @@ -49,6 +49,8 @@ border-radius: $radius-block-ui; opacity: 0.04; background: var(--wp-admin-theme-color); + // This fixes drag-and-drop in Firefox. + pointer-events: none; } } diff --git a/test/e2e/playwright.config.ts b/test/e2e/playwright.config.ts index 01f311d831fca..8796de6fdb28b 100644 --- a/test/e2e/playwright.config.ts +++ b/test/e2e/playwright.config.ts @@ -1,6 +1,7 @@ /** * External dependencies */ +import os from 'os'; import path from 'path'; import { fileURLToPath } from 'url'; import { devices } from '@playwright/test'; @@ -54,6 +55,30 @@ const config: PlaywrightTestConfig = { { name: 'chromium', use: { ...devices[ 'Desktop Chrome' ] }, + grepInvert: /-chromium/, + }, + { + name: 'webkit', + use: { + ...devices[ 'Desktop Safari' ], + /** + * Headless webkit won't receive dataTransfer with custom types in the + * drop event on Linux. The solution is to use `xvfb-run` to run the tests. + * ```sh + * xvfb-run npm run test:e2e:playwright + * ``` + * See `.github/workflows/end2end-test-playwright.yml` for advanced usages. + */ + headless: os.type() !== 'Linux', + }, + grep: /@webkit/, + grepInvert: /-webkit/, + }, + { + name: 'firefox', + use: { ...devices[ 'Desktop Firefox' ] }, + grep: /@firefox/, + grepInvert: /-firefox/, }, ], }; diff --git a/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-chromium.txt b/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-chromium.txt new file mode 100644 index 0000000000000..d5575ed006e9f --- /dev/null +++ b/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-chromium.txt @@ -0,0 +1,11 @@ + +

Dummy text

+ + + + + \ No newline at end of file diff --git a/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-webkit.txt b/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-webkit.txt new file mode 100644 index 0000000000000..d5575ed006e9f --- /dev/null +++ b/test/e2e/specs/editor/various/__snapshots__/Inserting-blocks-firefox-webkit-inserts-p-59603-ragging-and-dropping-from-the-global-inserter-1-webkit.txt @@ -0,0 +1,11 @@ + +

Dummy text

+ + + + + \ No newline at end of file diff --git a/test/e2e/specs/editor/various/inserting-blocks.spec.js b/test/e2e/specs/editor/various/inserting-blocks.spec.js new file mode 100644 index 0000000000000..043499a99921b --- /dev/null +++ b/test/e2e/specs/editor/various/inserting-blocks.spec.js @@ -0,0 +1,300 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.use( { + insertingBlocksUtils: async ( { page, editor }, use ) => { + await use( new InsertingBlocksUtils( { page, editor } ) ); + }, +} ); + +test.describe( 'Inserting blocks (@firefox, @webkit)', () => { + test.beforeEach( async ( { admin } ) => { + await admin.createNewPost(); + } ); + + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.deleteAllPosts(); + } ); + + test( 'inserts blocks by dragging and dropping from the global inserter', async ( { + 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.' + ); + + // 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' + ); + + 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]', + 'Heading' + ); + + await page.hover( + 'role=listbox[name="Blocks"i] >> role=option[name="Heading"i]' + ); + 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 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 ); + + // Expect the draggable-chip to appear. + await expect( insertingBlocksUtils.draggableChip ).toBeVisible(); + + await page.mouse.up(); + + await expect.poll( editor.getEditedPostContent ) + .toBe( ` +

Dummy text

+ + + +

+` ); + } ); + + test( 'cancels dragging blocks from the global inserter by pressing Escape', async ( { + page, + editor, + insertingBlocksUtils, + } ) => { + // 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 beforeContent = await editor.getEditedPostContent(); + + const paragraphBlock = page.locator( + '[data-type="core/paragraph"] >> text=Dummy text' + ); + + 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]', + 'Heading' + ); + + await page.hover( + 'role=listbox[name="Blocks"i] >> role=option[name="Heading"i]' + ); + 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 expect( insertingBlocksUtils.indicator ).toBeVisible(); + await expect( insertingBlocksUtils.draggableChip ).toBeVisible(); + + await page.keyboard.press( 'Escape' ); + + await expect( insertingBlocksUtils.indicator ).not.toBeVisible(); + await expect( insertingBlocksUtils.draggableChip ).not.toBeVisible(); + + await page.mouse.up(); + + await expect.poll( editor.getEditedPostContent ).toBe( beforeContent ); + } ); + + test( 'inserts patterns by dragging and dropping from the global inserter', async ( { + 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.' + ); + + // 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' + ); + + await page.click( + 'role=region[name="Editor top bar"i] >> role=button[name="Toggle block inserter"i]' + ); + + const PATTERN_NAME = 'Social links with a shared background color'; + + 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]` + ); + + // FIXME: I think we should show the indicator when hovering on patterns as well? + // await expect( insertingBlocksUtils.indicator ).toBeVisible(); + + 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 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 expect( insertingBlocksUtils.draggableChip ).toBeVisible(); + + await page.mouse.up(); + + expect( await editor.getEditedPostContent() ).toMatchSnapshot(); + } ); + + test( 'cancels dragging patterns from the global inserter by pressing Escape', async ( { + page, + editor, + insertingBlocksUtils, + } ) => { + // 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 beforeContent = await editor.getEditedPostContent(); + + const paragraphBlock = page.locator( + '[data-type="core/paragraph"] >> text=Dummy text' + ); + + await page.click( + 'role=region[name="Editor top bar"i] >> role=button[name="Toggle block inserter"i]' + ); + + const PATTERN_NAME = 'Social links with a shared background color'; + + 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(); + // 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 expect( insertingBlocksUtils.indicator ).toBeVisible(); + await expect( insertingBlocksUtils.draggableChip ).toBeVisible(); + + await page.keyboard.press( 'Escape' ); + + await expect( insertingBlocksUtils.indicator ).not.toBeVisible(); + await expect( insertingBlocksUtils.draggableChip ).not.toBeVisible(); + + await page.mouse.up(); + + await expect.poll( editor.getEditedPostContent ).toBe( beforeContent ); + } ); +} ); + +class InsertingBlocksUtils { + constructor( { page, editor } ) { + this.page = page; + this.editor = editor; + + this.indicator = this.page.locator( + 'data-testid=block-list-insertion-point-indicator' + ); + this.draggableChip = this.page.locator( + 'data-testid=block-draggable-chip >> visible=true' + ); + } +} From 04962f64363be814efe8da2b49c7475ab86c0ec9 Mon Sep 17 00:00:00 2001 From: Kai Hao Date: Wed, 12 Oct 2022 11:17:58 +0800 Subject: [PATCH 2/4] Add some doc about cross-browser testing --- test/e2e/README.md | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/test/e2e/README.md b/test/e2e/README.md index 56da393ea68fb..52ae79b11fbb3 100644 --- a/test/e2e/README.md +++ b/test/e2e/README.md @@ -58,6 +58,26 @@ Previously in our Jest + Puppeteer E2E tests, `page` and `browser` are exposed a We can insert as many assertions in one test as needed. It's better to make explicit assertions whenever possible. For instance, if we want to assert that a button exists before clicking on it, we can do `expect( locator ).toBeVisible()` before performing `locator.click()`. This makes the tests flow better and easier to read. +## Cross-browser testing + +By default, tests are only run in chromium. You can _tag_ tests to run them in different browsers. Use `@browser` anywhere in the test title to run it in that browser. Tests will always run in chromium by default, append `-chromium` to disable testing in chromium. Available browsers are `chromium`, `firefox`, and `webkit`. + +```js +test( 'I will run in @firefox and @webkit (and chromium by default)', async ( { page } ) => { + // ... +} ); + +test( 'I will only run in @firefox but not -chromium', async ( { page } ) => { + // ... +} ); + +test.describe( 'Grouping tests (@webkit, -chromium)', () => { + test( 'I will only run in webkit', async ( { page } ) => { + // ... + } ); +} ); +``` + ## Commands ```bash @@ -67,13 +87,26 @@ npm run test:e2e:playwright # Run in headed mode. npm run test:e2e:playwright -- --headed +# Run tests with specific browsers (`chromium`, `firefox`, or `webkit`). +npm run test:e2e:playwright -- --project=webkit --project=firefox + # Run a single test file. npm run test:e2e:playwright -- # E.g., npm run test:e2e:playwright -- site-editor/title.spec.js -# Debugging +# Debugging. npm run test:e2e:playwright -- --debug ``` +If you're developing in Linux, it currently requires testing Webkit browsers in headed mode. If you don't want to or can't run it with the GUI (e.g. if you don't have a graphic interface), prepend the command with [`xvfb-run`](https://manpages.ubuntu.com/manpages/xenial/man1/xvfb-run.1.html) to run it in a virtual environment. + +```bash +# Run all available tests. +xvfb-run npm run test:e2e:playwright + +# Only run webkit tests. +xvfb-run -- npm run test:e2e:playwright -- --project=webkit +``` + **Note**: This package requires Node.js 12.0.0 or later. It is not compatible with older versions.

Code is Poetry.

From d174d4d5e0b6051a60bf140971fc1b5412ca7014 Mon Sep 17 00:00:00 2001 From: Kai Hao Date: Fri, 21 Oct 2022 10:36:06 +0800 Subject: [PATCH 3/4] Keep changes atomic --- .github/workflows/end2end-test-playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/end2end-test-playwright.yml b/.github/workflows/end2end-test-playwright.yml index 7a92e57f65563..0e0c5e1ff8770 100644 --- a/.github/workflows/end2end-test-playwright.yml +++ b/.github/workflows/end2end-test-playwright.yml @@ -54,7 +54,7 @@ jobs: if: always() with: name: failures-artifacts - path: artifacts/test-results + path: artifacts if-no-files-found: ignore - name: Archive flaky tests report From ecb0a43794c0fa9ef57fb0f125fcbc05f039b117 Mon Sep 17 00:00:00 2001 From: Kai Hao Date: Fri, 21 Oct 2022 10:47:12 +0800 Subject: [PATCH 4/4] Add changelog and link the issue --- packages/block-editor/CHANGELOG.md | 4 ++++ test/e2e/specs/editor/various/inserting-blocks.spec.js | 1 + 2 files changed, 5 insertions(+) diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 1874e6f7852bc..25ebaac9760a8 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fix + +- `InserterListItem`: Fix dragging and dropping in Firefox. ([#44631](https://github.com/WordPress/gutenberg/pull/44631)) + ## 10.3.0 (2022-10-19) ### Bug Fix diff --git a/test/e2e/specs/editor/various/inserting-blocks.spec.js b/test/e2e/specs/editor/various/inserting-blocks.spec.js index 043499a99921b..cc75245d48bac 100644 --- a/test/e2e/specs/editor/various/inserting-blocks.spec.js +++ b/test/e2e/specs/editor/various/inserting-blocks.spec.js @@ -191,6 +191,7 @@ test.describe( 'Inserting blocks (@firefox, @webkit)', () => { ); // FIXME: I think we should show the indicator when hovering on patterns as well? + // @see https://github.com/WordPress/gutenberg/issues/45183 // await expect( insertingBlocksUtils.indicator ).toBeVisible(); const paragraphBoundingBox = await paragraphBlock.boundingBox();