From 12053c53371c6cbdb43a474be6c5ddef3c34e125 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Tue, 15 Nov 2022 12:42:34 -0800 Subject: [PATCH 01/17] Add new Playwright E2E tests for the cover block. --- test/e2e/specs/editor/blocks/cover.spec.js | 243 +++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 test/e2e/specs/editor/blocks/cover.spec.js diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js new file mode 100644 index 00000000000000..bc97296d12c2ac --- /dev/null +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -0,0 +1,243 @@ +/** + * External dependencies + */ +import path from 'path'; +import fs from 'fs'; +import os from 'os'; +import { v4 as uuid } from 'uuid'; + +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +async function getTestImage() { + const testImagePath = path.join( + __dirname, + '..', + '..', + '..', + 'assets', + '10x10_e2e_test_image_z9T8jK.png' + ); + const filename = uuid(); + const tmpFilename = path.join( os.tmpdir(), filename + '.png' ); + fs.copyFileSync( testImagePath, tmpFilename ); + return tmpFilename; +} + +test.describe( 'Cover', () => { + test.beforeEach( async ( { admin } ) => { + await admin.createNewPost(); + } ); + + test( 'can set overlay color using color picker on block placeholder', async ( { + page, + editor, + } ) => { + await editor.insertBlock( { name: 'core/cover' } ); + + // Locate the first color option from the block placeholder's color picker. + const firstColorPickerButton = page + .locator( 'button.components-circular-option-picker__option' ) + .first(); + + // Get the RGB value of the picked color. + await expect( firstColorPickerButton ).toBeVisible(); + const pickedColor = await firstColorPickerButton.evaluate( + ( node ) => node.style.backgroundColor + ); + + // Create the block by clicking selected color button. + await firstColorPickerButton.click(); + + // Get the block's background dim element. + const backgrounDimLocator = page.locator( + '.wp-block-cover .has-background-dim' + ); + await backgrounDimLocator.waitFor(); + // Get the RGB value of the background dim. + const dimColor = await backgrounDimLocator.evaluate( + ( node ) => node.style.backgroundColor + ); + + expect( pickedColor ).toEqual( dimColor ); + } ); + + test( 'can set background image using image upload on block placeholder', async ( { + page, + editor, + } ) => { + await editor.insertBlock( { name: 'core/cover' } ); + + // Create a test image. + const testImage = await getTestImage(); + + // Create the block using uploaded image. + await page + .locator( `.wp-block-cover input[type="file"]` ) + .setInputFiles( testImage ); + + const testImageFilename = path.basename( testImage ); + + const backgroundImageLocator = page.locator( + `.wp-block-cover img[src$="${ testImageFilename }"]` + ); + + // Get the block's background image URL. + const backgroundImageURL = await backgroundImageLocator.evaluate( + ( el ) => el.src + ); + expect( backgroundImageURL ).toContain( testImageFilename ); + } ); + + test( 'dims background image down by 50% by default', async ( { + page, + editor, + } ) => { + await editor.insertBlock( { name: 'core/cover' } ); + + // Create a test image. + const testImage = await getTestImage(); + + // Create the block using uploaded image. + await page + .locator( `.wp-block-cover input[type="file"]` ) + .setInputFiles( testImage ); + + const [ backgroundDimColor, backgroundDimOpacity ] = await page + .locator( '.wp-block-cover .has-background-dim' ) + .evaluate( ( el ) => { + const computedStyle = window.getComputedStyle( el ); + return [ computedStyle.backgroundColor, computedStyle.opacity ]; + } ); + + expect( backgroundDimColor ).toBe( 'rgb(0, 0, 0)' ); + expect( backgroundDimOpacity ).toBe( '0.5' ); + } ); + + test( 'can have the title edited', async ( { page, editor } ) => { + await editor.insertBlock( { name: 'core/cover' } ); + + // Locate the first color option from the block placeholder's color picker. + await page + .locator( 'button.components-circular-option-picker__option' ) + .first() + .click(); + + // Click on the placeholder text to activate cursor inside. + const coverTitle = page.locator( '[data-title="Paragraph"]' ); + await expect( coverTitle ).toBeVisible(); + await coverTitle.click(); + + // Type the title. + await page.keyboard.type( 'foo' ); + const coverTitleText = await coverTitle.innerText(); + + expect( coverTitleText ).toEqual( 'foo' ); + } ); + + test( 'can be resized using drag & drop', async ( { page, editor } ) => { + await editor.insertBlock( { name: 'core/cover' } ); + + // Open the document sidebar. + await editor.openDocumentSettingsSidebar(); + + // Locate the first color option from the block placeholder's color picker. + await page + .locator( 'button.components-circular-option-picker__option' ) + .first() + .click(); + + // Open the block list viewer and select child paragraph within the cover block. + await page.locator( '[aria-label="List View"]' ).click(); + await page + .locator( + '[aria-label="Block navigation structure"] [aria-label="Cover link"]' + ) + .click(); + + const coverHeightInput = page.locator( + 'role=spinbutton[name="Minimum height of cover"]' + ); + await expect( coverHeightInput ).not.toHaveValue( /[0-9]/ ); + + const coverBlockBoundingBox = await page + .locator( '[aria-label="Block: Cover"]' ) + .boundingBox(); + + const boundingBoxResizeButton = await page + .locator( '.components-resizable-box__handle-bottom' ) + .boundingBox(); + const coordinatesResizeButton = { + x: boundingBoxResizeButton.x + boundingBoxResizeButton.width / 2, + y: boundingBoxResizeButton.y + boundingBoxResizeButton.height / 2, + }; + + // Move the mouse to the position of the resize button. + await page.mouse.move( + coordinatesResizeButton.x, + coordinatesResizeButton.y + ); + await page + .locator( '.components-resizable-box__handle-bottom' ) + .hover(); + await page.mouse.down(); + await page.mouse.move( + coordinatesResizeButton.x, + coordinatesResizeButton.y + 100, + { steps: 10 } + ); + await page.mouse.up(); + + const newCoverBlockBoundingBox = await page + .locator( '[aria-label="Block: Cover"]' ) + .boundingBox(); + + expect( newCoverBlockBoundingBox.height ).toBeGreaterThanOrEqual( + coverBlockBoundingBox.height + 100 + ); + await expect( coverHeightInput ).toHaveValue( + newCoverBlockBoundingBox.height.toString() + ); + } ); + + test( 'dims the background image down by 50% when transformed from the Image block', async ( { + page, + editor, + } ) => { + await editor.insertBlock( { name: 'core/image' } ); + + // Upload image and transform to the Cover block. + const testImage = await getTestImage(); + + // Create the block using uploaded image. + await page + .locator( `.wp-block-image input[type="file"]` ) + .setInputFiles( testImage ); + + await expect( + page.locator( + `.wp-block-image img[src$="${ path.basename( testImage ) }"]` + ) + ).toBeVisible(); + + await page.locator( '.wp-block-image' ).focus(); + await editor.transformBlockTo( 'core/cover' ); + + // Get the block's background dim color and its opacity. + await expect( + page.locator( '.wp-block-cover .has-background-dim' ) + ).toBeEnabled(); + + const [ backgroundDimColor, backgroundDimOpacity ] = await page + .locator( '.wp-block-cover .has-background-dim' ) + .evaluate( ( el ) => { + const computedStyle = window.getComputedStyle( el ); + return [ computedStyle.backgroundColor, computedStyle.opacity ]; + } ); + + expect( backgroundDimColor ).toBe( 'rgb(0, 0, 0)' ); + expect( backgroundDimOpacity ).toBe( '0.5' ); + } ); +} ); From 4ad16be91966d264c34f26f7fe97665fb82da518 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Tue, 15 Nov 2022 12:48:20 -0800 Subject: [PATCH 02/17] Add comment --- test/e2e/specs/editor/blocks/cover.spec.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index bc97296d12c2ac..95c36a1972d4d2 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -179,6 +179,8 @@ test.describe( 'Cover', () => { coordinatesResizeButton.x, coordinatesResizeButton.y ); + + // Resize the block by at least 100px. await page .locator( '.components-resizable-box__handle-bottom' ) .hover(); From ff1b3c337f26ca24f3efd7621766dfee2db601a0 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Thu, 17 Nov 2022 10:57:03 -0800 Subject: [PATCH 03/17] Update block list selector --- test/e2e/specs/editor/blocks/cover.spec.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index 95c36a1972d4d2..38eb88ce5704c4 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -150,7 +150,9 @@ test.describe( 'Cover', () => { .click(); // Open the block list viewer and select child paragraph within the cover block. - await page.locator( '[aria-label="List View"]' ).click(); + await page + .locator( 'button.edit-post-header-toolbar__list-view-toggle' ) + .click(); await page .locator( '[aria-label="Block navigation structure"] [aria-label="Cover link"]' From 1594c2d897e8908ea50a46cee23f5f6120910afe Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Wed, 26 Apr 2023 18:21:48 +0900 Subject: [PATCH 04/17] test/e2e/specs/editor/blocks/cover.spec.js - update spec with accessibility-based selectors where possible. --- test/e2e/specs/editor/blocks/cover.spec.js | 217 ++++++++++----------- 1 file changed, 106 insertions(+), 111 deletions(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index 38eb88ce5704c4..c11acb0755a5ff 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -26,6 +26,13 @@ async function getTestImage() { return tmpFilename; } +async function getBackgroundColorAndOpacity( locator ) { + return await locator.evaluate( ( el ) => { + const computedStyle = window.getComputedStyle( el ); + return [ computedStyle.backgroundColor, computedStyle.opacity ]; + } ); +} + test.describe( 'Cover', () => { test.beforeEach( async ( { admin } ) => { await admin.createNewPost(); @@ -37,31 +44,31 @@ test.describe( 'Cover', () => { } ) => { await editor.insertBlock( { name: 'core/cover' } ); - // Locate the first color option from the block placeholder's color picker. - const firstColorPickerButton = page - .locator( 'button.components-circular-option-picker__option' ) - .first(); + // Locate the Black color swatch. + const blackColorSwatch = page.getByRole( 'button', { + name: 'Color: Black', + } ); + await expect( blackColorSwatch ).toBeVisible(); - // Get the RGB value of the picked color. - await expect( firstColorPickerButton ).toBeVisible(); - const pickedColor = await firstColorPickerButton.evaluate( + // Get the RGB value of Black. + const blackRGB = await blackColorSwatch.evaluate( ( node ) => node.style.backgroundColor ); // Create the block by clicking selected color button. - await firstColorPickerButton.click(); + await blackColorSwatch.click(); + + // Get the block's background image's dim level. + const backgrounDimLocator = page + .getByRole( 'document', { name: 'Block: Cover' } ) + .locator( 'span[aria-hidden="true"]' ); - // Get the block's background dim element. - const backgrounDimLocator = page.locator( - '.wp-block-cover .has-background-dim' - ); - await backgrounDimLocator.waitFor(); // Get the RGB value of the background dim. - const dimColor = await backgrounDimLocator.evaluate( + const actualRGB = await backgrounDimLocator.evaluate( ( node ) => node.style.backgroundColor ); - expect( pickedColor ).toEqual( dimColor ); + expect( blackRGB ).toEqual( actualRGB ); } ); test( 'can set background image using image upload on block placeholder', async ( { @@ -70,24 +77,25 @@ test.describe( 'Cover', () => { } ) => { await editor.insertBlock( { name: 'core/cover' } ); - // Create a test image. const testImage = await getTestImage(); + const testImageFilename = path.basename( testImage ); - // Create the block using uploaded image. - await page - .locator( `.wp-block-cover input[type="file"]` ) + const coverBlock = page.getByRole( 'document', { + name: 'Block: Cover', + } ); + + await coverBlock + .getByTestId( 'form-file-upload-input' ) .setInputFiles( testImage ); - const testImageFilename = path.basename( testImage ); + // Wait for the img's src attribute to be prefixed with http. + // Otherwise, the URL for the img src attribute is that of a placeholder. + await coverBlock.locator( `img[src^=http]` ).waitFor(); - const backgroundImageLocator = page.locator( - `.wp-block-cover img[src$="${ testImageFilename }"]` - ); + const backgroundImageURL = await coverBlock + .locator( 'img' ) + .getAttribute( 'src' ); - // Get the block's background image URL. - const backgroundImageURL = await backgroundImageLocator.evaluate( - ( el ) => el.src - ); expect( backgroundImageURL ).toContain( testImageFilename ); } ); @@ -97,44 +105,47 @@ test.describe( 'Cover', () => { } ) => { await editor.insertBlock( { name: 'core/cover' } ); - // Create a test image. const testImage = await getTestImage(); - // Create the block using uploaded image. - await page - .locator( `.wp-block-cover input[type="file"]` ) - .setInputFiles( testImage ); + const coverBlock = page.getByRole( 'document', { + name: 'Block: Cover', + } ); - const [ backgroundDimColor, backgroundDimOpacity ] = await page - .locator( '.wp-block-cover .has-background-dim' ) - .evaluate( ( el ) => { - const computedStyle = window.getComputedStyle( el ); - return [ computedStyle.backgroundColor, computedStyle.opacity ]; - } ); + await coverBlock + .getByTestId( 'form-file-upload-input' ) + .setInputFiles( testImage ); + const [ backgroundDimColor, backgroundDimOpacity ] = + await getBackgroundColorAndOpacity( + coverBlock.locator( 'span[aria-hidden="true"]' ) + ); expect( backgroundDimColor ).toBe( 'rgb(0, 0, 0)' ); expect( backgroundDimOpacity ).toBe( '0.5' ); } ); test( 'can have the title edited', async ( { page, editor } ) => { + const titleText = 'foo'; + await editor.insertBlock( { name: 'core/cover' } ); - // Locate the first color option from the block placeholder's color picker. + // Choose a color swatch to transform the placeholder block into + // a functioning block. await page - .locator( 'button.components-circular-option-picker__option' ) - .first() + .getByRole( 'button', { + name: 'Color: Black', + } ) .click(); - // Click on the placeholder text to activate cursor inside. - const coverTitle = page.locator( '[data-title="Paragraph"]' ); - await expect( coverTitle ).toBeVisible(); - await coverTitle.click(); + // Activate the paragraph block inside the Cover block. + // The name of the block differs depending on whether text has been entered or not. + const coverParagraphLocator = page.getByRole( 'document', { + name: /Paragraph block|Empty block; start writing or type forward slash to choose a block/, + } ); + await expect( coverParagraphLocator ).toBeEditable(); - // Type the title. - await page.keyboard.type( 'foo' ); - const coverTitleText = await coverTitle.innerText(); + await coverParagraphLocator.fill( titleText ); - expect( coverTitleText ).toEqual( 'foo' ); + await expect( coverParagraphLocator ).toContainText( titleText ); } ); test( 'can be resized using drag & drop', async ( { page, editor } ) => { @@ -143,103 +154,87 @@ test.describe( 'Cover', () => { // Open the document sidebar. await editor.openDocumentSettingsSidebar(); - // Locate the first color option from the block placeholder's color picker. await page - .locator( 'button.components-circular-option-picker__option' ) - .first() + .getByRole( 'button', { + name: 'Color: Black', + } ) .click(); - // Open the block list viewer and select child paragraph within the cover block. - await page - .locator( 'button.edit-post-header-toolbar__list-view-toggle' ) - .click(); + // Open the block list viewer from the toolbar. await page - .locator( - '[aria-label="Block navigation structure"] [aria-label="Cover link"]' - ) + .getByRole( 'toolbar', { name: 'Document tools' } ) + .getByRole( 'button', { name: 'List View' } ) .click(); - const coverHeightInput = page.locator( - 'role=spinbutton[name="Minimum height of cover"]' - ); + // Select the Cover block. + await page.getByRole( 'gridcell', { name: 'Cover link' } ).click(); + + // Ensure there the default value for the minimum height of cover is undefined. + const coverHeightInput = page.getByLabel( 'Minimum height of cover' ); await expect( coverHeightInput ).not.toHaveValue( /[0-9]/ ); - const coverBlockBoundingBox = await page - .locator( '[aria-label="Block: Cover"]' ) - .boundingBox(); + // Establish locators for the Cover block and the resize handler. + const coverBlock = page.getByRole( 'document', { + name: 'Block: Cover', + } ); + const coverBlockResizeHandle = coverBlock.locator( + '.components-resizable-box__handle' + ); - const boundingBoxResizeButton = await page - .locator( '.components-resizable-box__handle-bottom' ) - .boundingBox(); - const coordinatesResizeButton = { - x: boundingBoxResizeButton.x + boundingBoxResizeButton.width / 2, - y: boundingBoxResizeButton.y + boundingBoxResizeButton.height / 2, - }; + // Establish the existing bounding boxes for the Cover block and the + // resize handler. + const coverBlockBox = await coverBlock.boundingBox(); + const coverBlockResizeHandleBox = + await coverBlockResizeHandle.boundingBox(); - // Move the mouse to the position of the resize button. - await page.mouse.move( - coordinatesResizeButton.x, - coordinatesResizeButton.y - ); + expect( coverBlockBox.height ).toEqual( 450 ); // Resize the block by at least 100px. - await page - .locator( '.components-resizable-box__handle-bottom' ) - .hover(); + await coverBlockResizeHandle.hover(); await page.mouse.down(); await page.mouse.move( - coordinatesResizeButton.x, - coordinatesResizeButton.y + 100, - { steps: 10 } + coverBlockResizeHandleBox.x, + coverBlockBox.y + coverBlockBox.height + 100, + { steps: 5 } ); await page.mouse.up(); - const newCoverBlockBoundingBox = await page - .locator( '[aria-label="Block: Cover"]' ) - .boundingBox(); - - expect( newCoverBlockBoundingBox.height ).toBeGreaterThanOrEqual( - coverBlockBoundingBox.height + 100 - ); - await expect( coverHeightInput ).toHaveValue( - newCoverBlockBoundingBox.height.toString() + const newCoverBlockBox = await coverBlock.boundingBox(); + expect( newCoverBlockBox.height ).toBeGreaterThanOrEqual( + coverBlockBox.height + 100 ); } ); - test( 'dims the background image down by 50% when transformed from the Image block', async ( { + test.skip( 'dims the background image down by 50% when transformed from the Image block', async ( { page, editor, } ) => { await editor.insertBlock( { name: 'core/image' } ); - // Upload image and transform to the Cover block. const testImage = await getTestImage(); - // Create the block using uploaded image. await page - .locator( `.wp-block-image input[type="file"]` ) + .getByTestId( 'form-file-upload-input' ) .setInputFiles( testImage ); await expect( - page.locator( - `.wp-block-image img[src$="${ path.basename( testImage ) }"]` - ) + page + .getByRole( 'document', { name: 'Block: Image' } ) + .locator( 'img' ) ).toBeVisible(); - await page.locator( '.wp-block-image' ).focus(); await editor.transformBlockTo( 'core/cover' ); - // Get the block's background dim color and its opacity. - await expect( - page.locator( '.wp-block-cover .has-background-dim' ) - ).toBeEnabled(); - - const [ backgroundDimColor, backgroundDimOpacity ] = await page - .locator( '.wp-block-cover .has-background-dim' ) - .evaluate( ( el ) => { - const computedStyle = window.getComputedStyle( el ); - return [ computedStyle.backgroundColor, computedStyle.opacity ]; - } ); + const coverBlockBackground = page + .getByRole( 'document', { + name: 'Block: Cover', + } ) + .locator( 'span[aria-hidden="true"]' ); + + await expect( coverBlockBackground ).toBeVisible(); + + const [ backgroundDimColor, backgroundDimOpacity ] = + await getBackgroundColorAndOpacity( coverBlockBackground ); expect( backgroundDimColor ).toBe( 'rgb(0, 0, 0)' ); expect( backgroundDimOpacity ).toBe( '0.5' ); From 2a496d1a502d26b7f65f207eecab2d3c883543f8 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Thu, 27 Apr 2023 17:26:12 +0900 Subject: [PATCH 05/17] test/e2e/specs/editor/blocks/cover.spec.js - rebase, rebuild and update the selectors --- test/e2e/specs/editor/blocks/cover.spec.js | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index c11acb0755a5ff..fb19a35ba356fa 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -163,37 +163,37 @@ test.describe( 'Cover', () => { // Open the block list viewer from the toolbar. await page .getByRole( 'toolbar', { name: 'Document tools' } ) - .getByRole( 'button', { name: 'List View' } ) + .getByRole( 'button', { name: 'Document Overview' } ) .click(); - // Select the Cover block. - await page.getByRole( 'gridcell', { name: 'Cover link' } ).click(); + // Select the Cover block from the docuemnt overview. + await page.getByRole( 'link', { name: 'Cover' } ).click(); // Ensure there the default value for the minimum height of cover is undefined. - const coverHeightInput = page.getByLabel( 'Minimum height of cover' ); - await expect( coverHeightInput ).not.toHaveValue( /[0-9]/ ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); + const defaultHeightValue = await page + .getByLabel( 'Minimum height of cover' ) + .inputValue(); + expect( defaultHeightValue ).toBeFalsy(); // Establish locators for the Cover block and the resize handler. const coverBlock = page.getByRole( 'document', { name: 'Block: Cover', } ); - const coverBlockResizeHandle = coverBlock.locator( - '.components-resizable-box__handle' + const coverBlockResizeHandle = page.locator( + '.components-resizable-box__handle-bottom' ); - // Establish the existing bounding boxes for the Cover block and the - // resize handler. + // Establish the existing bounding boxes for the Cover block. const coverBlockBox = await coverBlock.boundingBox(); - const coverBlockResizeHandleBox = - await coverBlockResizeHandle.boundingBox(); expect( coverBlockBox.height ).toEqual( 450 ); - // Resize the block by at least 100px. + // Resize the block by 100px. await coverBlockResizeHandle.hover(); await page.mouse.down(); await page.mouse.move( - coverBlockResizeHandleBox.x, + coverBlockBox.x, coverBlockBox.y + coverBlockBox.height + 100, { steps: 5 } ); @@ -205,7 +205,7 @@ test.describe( 'Cover', () => { ); } ); - test.skip( 'dims the background image down by 50% when transformed from the Image block', async ( { + test( 'dims the background image down by 50% when transformed from the Image block', async ( { page, editor, } ) => { From e409acf68f86c905afff92ed1478e5ac3e97bd92 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Thu, 27 Apr 2023 18:46:06 +0900 Subject: [PATCH 06/17] packages/e2e-tests/specs/editor/blocks/cover.test.js - remove Puppeteer file. --- .../specs/editor/blocks/cover.test.js | 177 ------------------ 1 file changed, 177 deletions(-) delete mode 100644 packages/e2e-tests/specs/editor/blocks/cover.test.js diff --git a/packages/e2e-tests/specs/editor/blocks/cover.test.js b/packages/e2e-tests/specs/editor/blocks/cover.test.js deleted file mode 100644 index 56ed8455aefa9c..00000000000000 --- a/packages/e2e-tests/specs/editor/blocks/cover.test.js +++ /dev/null @@ -1,177 +0,0 @@ -/** - * External dependencies - */ -import path from 'path'; -import fs from 'fs'; -import os from 'os'; -import { v4 as uuid } from 'uuid'; - -/** - * WordPress dependencies - */ -import { - insertBlock, - createNewPost, - openDocumentSettingsSidebar, - switchBlockInspectorTab, - transformBlockTo, -} from '@wordpress/e2e-test-utils'; - -async function upload( selector ) { - const inputElement = await page.waitForSelector( - `${ selector } input[type="file"]` - ); - const testImagePath = path.join( - __dirname, - '..', - '..', - '..', - 'assets', - '10x10_e2e_test_image_z9T8jK.png' - ); - const filename = uuid(); - const tmpFileName = path.join( os.tmpdir(), filename + '.png' ); - fs.copyFileSync( testImagePath, tmpFileName ); - await inputElement.uploadFile( tmpFileName ); - await page.waitForSelector( `${ selector } img[src$="${ filename }.png"]` ); - return filename; -} - -describe( 'Cover', () => { - beforeEach( async () => { - await createNewPost(); - } ); - - it( 'can set background image using image upload on block placeholder', async () => { - await insertBlock( 'Cover' ); - // Create the block using uploaded image. - const sourceImageFilename = await upload( '.wp-block-cover' ); - // Get the block's background image URL. - const blockImage = await page.waitForSelector( '.wp-block-cover img' ); - const blockImageUrl = await blockImage.evaluate( ( el ) => el.src ); - - expect( blockImageUrl ).toContain( sourceImageFilename ); - } ); - - it( 'dims background image down by 50% by default', async () => { - await insertBlock( 'Cover' ); - // Create the block using uploaded image. - await upload( '.wp-block-cover' ); - // Get the block's background dim color and its opacity. - const backgroundDim = await page.waitForSelector( - '.wp-block-cover .has-background-dim' - ); - const [ backgroundDimColor, backgroundDimOpacity ] = - await page.evaluate( ( el ) => { - const computedStyle = window.getComputedStyle( el ); - return [ computedStyle.backgroundColor, computedStyle.opacity ]; - }, backgroundDim ); - - expect( backgroundDimColor ).toBe( 'rgb(0, 0, 0)' ); - expect( backgroundDimOpacity ).toBe( '0.5' ); - } ); - - it( 'can be resized using drag & drop', async () => { - await insertBlock( 'Cover' ); - // Close the inserter. - await page.click( '.edit-post-header-toolbar__inserter-toggle' ); - // Open the sidebar. - await openDocumentSettingsSidebar(); - // Choose the first solid color as the background of the cover. - await page.click( - '.components-circular-option-picker__option-wrapper:first-child button' - ); - - // Select the cover block. By default the child paragraph gets selected. - await page.click( - '.edit-post-header-toolbar__document-overview-toggle' - ); - await page.click( - '.block-editor-list-view-block__contents-container a' - ); - - switchBlockInspectorTab( 'Styles' ); - const heightInputHandle = await page.waitForSelector( - 'input[id*="block-cover-height-input"]' - ); - - // Verify the height of the cover is not defined. - expect( - await page.evaluate( ( { value } ) => value, heightInputHandle ) - ).toBe( '' ); - - const resizeButton = await page.$( - '.components-resizable-box__handle-bottom' - ); - const boundingBoxResizeButton = await resizeButton.boundingBox(); - const coordinatesResizeButton = { - x: boundingBoxResizeButton.x + boundingBoxResizeButton.width / 2, - y: boundingBoxResizeButton.y + boundingBoxResizeButton.height / 2, - }; - - // Move the mouse to the position of the resize button. - await page.mouse.move( - coordinatesResizeButton.x, - coordinatesResizeButton.y - ); - - // Trigger a mousedown event against the resize button. - // Using page.mouse.down does not works because it triggers a global event, - // not an event for that element. - page.evaluate( ( { x, y } ) => { - const element = document.querySelector( - '.components-resizable-box__handle-bottom' - ); - event = document.createEvent( 'CustomEvent' ); - event.initCustomEvent( 'mousedown', true, true, null ); - event.clientX = x; - event.clientY = y; - element.dispatchEvent( event ); - }, coordinatesResizeButton ); - - // Move the mouse to resize the cover. - await page.mouse.move( - coordinatesResizeButton.x, - coordinatesResizeButton.y + 100, - { steps: 10 } - ); - - // Release the mouse. - await page.mouse.up(); - - // Verify the height of the cover has changed. - expect( - await page.evaluate( - ( { value } ) => Number.parseInt( value ), - heightInputHandle - ) - ).toBeGreaterThan( 100 ); - } ); - - it( 'dims the background image down by 50% when transformed from the Image block', async () => { - await insertBlock( 'Image' ); - // Upload image and transform to the Cover block. - const filename = await upload( '.wp-block-image' ); - await page.waitForSelector( - `.wp-block-image img[src$="${ filename }.png"]` - ); - - // Focus the block wrapper before trying to convert to make sure figcaption toolbar is not obscuring - // the block toolbar. - await page.focus( '.wp-block-image' ); - await transformBlockTo( 'Cover' ); - - // Get the block's background dim color and its opacity. - const backgroundDim = await page.waitForSelector( - '.wp-block-cover .has-background-dim' - ); - const [ backgroundDimColor, backgroundDimOpacity ] = - await page.evaluate( ( el ) => { - const computedStyle = window.getComputedStyle( el ); - return [ computedStyle.backgroundColor, computedStyle.opacity ]; - }, backgroundDim ); - - expect( backgroundDimColor ).toBe( 'rgb(0, 0, 0)' ); - expect( backgroundDimOpacity ).toBe( '0.5' ); - } ); -} ); From c1546408a2261e554de958465d0aa45db54535ba Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Thu, 27 Apr 2023 18:50:57 +0900 Subject: [PATCH 07/17] test/e2e/specs/editor/blocks/cover.spec.js - clarify use of `span` element in the first spec. --- test/e2e/specs/editor/blocks/cover.spec.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index fb19a35ba356fa..7c0facc6b5e637 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -58,12 +58,11 @@ test.describe( 'Cover', () => { // Create the block by clicking selected color button. await blackColorSwatch.click(); - // Get the block's background image's dim level. + // Get the RGB value of the background dim. + // The span element implements the colored background. const backgrounDimLocator = page .getByRole( 'document', { name: 'Block: Cover' } ) .locator( 'span[aria-hidden="true"]' ); - - // Get the RGB value of the background dim. const actualRGB = await backgrounDimLocator.evaluate( ( node ) => node.style.backgroundColor ); From 071c31b4fe4685041cbd67bfe90e7d5f27131a0c Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Wed, 10 May 2023 12:29:08 +0900 Subject: [PATCH 08/17] - add comment explaing use of CSS selector for '.components-resizable-box__handle-bottom'. - move image upload and filename methods previously handled by `getTestImage` into a POM-like function at bottom of file. --- test/e2e/specs/editor/blocks/cover.spec.js | 89 ++++++++++++++-------- 1 file changed, 57 insertions(+), 32 deletions(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index 7c0facc6b5e637..6f3fe25274f10e 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -2,29 +2,22 @@ * External dependencies */ import path from 'path'; -import fs from 'fs'; +const fs = require( 'fs/promises' ); import os from 'os'; import { v4 as uuid } from 'uuid'; +/** @typedef {import('@playwright/test').Page} Page */ + /** * WordPress dependencies */ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); -async function getTestImage() { - const testImagePath = path.join( - __dirname, - '..', - '..', - '..', - 'assets', - '10x10_e2e_test_image_z9T8jK.png' - ); - const filename = uuid(); - const tmpFilename = path.join( os.tmpdir(), filename + '.png' ); - fs.copyFileSync( testImagePath, tmpFilename ); - return tmpFilename; -} +test.use( { + imageBlockUtils: async ( { page }, use ) => { + await use( new ImageBlockUtils( { page } ) ); + }, +} ); async function getBackgroundColorAndOpacity( locator ) { return await locator.evaluate( ( el ) => { @@ -73,19 +66,18 @@ test.describe( 'Cover', () => { test( 'can set background image using image upload on block placeholder', async ( { page, editor, + imageBlockUtils, } ) => { await editor.insertBlock( { name: 'core/cover' } ); - const testImage = await getTestImage(); - const testImageFilename = path.basename( testImage ); - const coverBlock = page.getByRole( 'document', { name: 'Block: Cover', } ); - await coverBlock - .getByTestId( 'form-file-upload-input' ) - .setInputFiles( testImage ); + const filename = await imageBlockUtils.upload( + coverBlock.getByTestId( 'form-file-upload-input' ) + ); + const fileBasename = path.basename( filename ); // Wait for the img's src attribute to be prefixed with http. // Otherwise, the URL for the img src attribute is that of a placeholder. @@ -95,24 +87,23 @@ test.describe( 'Cover', () => { .locator( 'img' ) .getAttribute( 'src' ); - expect( backgroundImageURL ).toContain( testImageFilename ); + expect( backgroundImageURL ).toContain( fileBasename ); } ); test( 'dims background image down by 50% by default', async ( { page, editor, + imageBlockUtils, } ) => { await editor.insertBlock( { name: 'core/cover' } ); - const testImage = await getTestImage(); - const coverBlock = page.getByRole( 'document', { name: 'Block: Cover', } ); - await coverBlock - .getByTestId( 'form-file-upload-input' ) - .setInputFiles( testImage ); + await imageBlockUtils.upload( + coverBlock.getByTestId( 'form-file-upload-input' ) + ); const [ backgroundDimColor, backgroundDimOpacity ] = await getBackgroundColorAndOpacity( @@ -179,6 +170,8 @@ test.describe( 'Cover', () => { const coverBlock = page.getByRole( 'document', { name: 'Block: Cover', } ); + // There is no accessible locator for this element, which is a + // bottom edge of the Cover block for resizing. const coverBlockResizeHandle = page.locator( '.components-resizable-box__handle-bottom' ); @@ -204,17 +197,20 @@ test.describe( 'Cover', () => { ); } ); - test( 'dims the background image down by 50% when transformed from the Image block', async ( { + test.only( 'dims the background image down by 50% when transformed from the Image block', async ( { page, editor, + imageBlockUtils, } ) => { await editor.insertBlock( { name: 'core/image' } ); - const testImage = await getTestImage(); + const imageBlock = page.getByRole( 'document', { + name: 'Block: Image', + } ); - await page - .getByTestId( 'form-file-upload-input' ) - .setInputFiles( testImage ); + await imageBlockUtils.upload( + imageBlock.getByTestId( 'form-file-upload-input' ) + ); await expect( page @@ -239,3 +235,32 @@ test.describe( 'Cover', () => { expect( backgroundDimOpacity ).toBe( '0.5' ); } ); } ); + +class ImageBlockUtils { + constructor( { page } ) { + /** @type {Page} */ + this.page = page; + + this.TEST_IMAGE_FILE_PATH = path.join( + __dirname, + '..', + '..', + '..', + 'assets', + '10x10_e2e_test_image_z9T8jK.png' + ); + } + + async upload( inputElement ) { + const tmpDirectory = await fs.mkdtemp( + path.join( os.tmpdir(), 'gutenberg-test-image-' ) + ); + const filename = uuid(); + const tmpFileName = path.join( tmpDirectory, filename + '.png' ); + await fs.copyFile( this.TEST_IMAGE_FILE_PATH, tmpFileName ); + + await inputElement.setInputFiles( tmpFileName ); + + return filename; + } +} From 77a1b7bea01af2eb9215d67f3cd806322680e584 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Wed, 10 May 2023 12:32:01 +0900 Subject: [PATCH 09/17] - remove testing `test.only` --- test/e2e/specs/editor/blocks/cover.spec.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index 6f3fe25274f10e..e0f30783b10db9 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -13,12 +13,6 @@ import { v4 as uuid } from 'uuid'; */ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); -test.use( { - imageBlockUtils: async ( { page }, use ) => { - await use( new ImageBlockUtils( { page } ) ); - }, -} ); - async function getBackgroundColorAndOpacity( locator ) { return await locator.evaluate( ( el ) => { const computedStyle = window.getComputedStyle( el ); @@ -26,6 +20,12 @@ async function getBackgroundColorAndOpacity( locator ) { } ); } +test.use( { + imageBlockUtils: async ( { page }, use ) => { + await use( new ImageBlockUtils( { page } ) ); + }, +} ); + test.describe( 'Cover', () => { test.beforeEach( async ( { admin } ) => { await admin.createNewPost(); @@ -197,7 +197,7 @@ test.describe( 'Cover', () => { ); } ); - test.only( 'dims the background image down by 50% when transformed from the Image block', async ( { + test( 'dims the background image down by 50% when transformed from the Image block', async ( { page, editor, imageBlockUtils, From 6d20287228b3de67acc86cc88e8114e6fe555db2 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Wed, 10 May 2023 16:26:00 +0900 Subject: [PATCH 10/17] - define the coverBlock locator after inserting the block, and use that locator as starting point for all other interactions. - use `getComputedStyle` instad of `node.style.`. - replace implementation detail check on image upload with a `expect.toPass` check. - remove steps when resizing box. - replace implementation detail check for coverbox height with truthy check. --- test/e2e/specs/editor/blocks/cover.spec.js | 65 +++++++++++----------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index e0f30783b10db9..3d2dc3aa63dfa9 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -36,28 +36,27 @@ test.describe( 'Cover', () => { editor, } ) => { await editor.insertBlock( { name: 'core/cover' } ); + const coverBlock = page.getByRole( 'document', { + name: 'Block: Cover', + } ); // Locate the Black color swatch. - const blackColorSwatch = page.getByRole( 'button', { + const blackColorSwatch = coverBlock.getByRole( 'button', { name: 'Color: Black', } ); await expect( blackColorSwatch ).toBeVisible(); // Get the RGB value of Black. const blackRGB = await blackColorSwatch.evaluate( - ( node ) => node.style.backgroundColor + ( element ) => window.getComputedStyle( element ).color ); // Create the block by clicking selected color button. await blackColorSwatch.click(); // Get the RGB value of the background dim. - // The span element implements the colored background. - const backgrounDimLocator = page - .getByRole( 'document', { name: 'Block: Cover' } ) - .locator( 'span[aria-hidden="true"]' ); - const actualRGB = await backgrounDimLocator.evaluate( - ( node ) => node.style.backgroundColor + const actualRGB = await coverBlock.evaluate( + ( element ) => window.getComputedStyle( element ).backgroundColor ); expect( blackRGB ).toEqual( actualRGB ); @@ -69,7 +68,6 @@ test.describe( 'Cover', () => { imageBlockUtils, } ) => { await editor.insertBlock( { name: 'core/cover' } ); - const coverBlock = page.getByRole( 'document', { name: 'Block: Cover', } ); @@ -80,8 +78,12 @@ test.describe( 'Cover', () => { const fileBasename = path.basename( filename ); // Wait for the img's src attribute to be prefixed with http. - // Otherwise, the URL for the img src attribute is that of a placeholder. - await coverBlock.locator( `img[src^=http]` ).waitFor(); + // Otherwise, the URL for the img src attribute starts is a placeholder + // beginning with `blob`. + await expect( async () => { + const src = await coverBlock.locator( 'img' ).getAttribute( 'src' ); + expect( src.startsWith( 'http' ) ).toBe( true ); + } ).toPass(); const backgroundImageURL = await coverBlock .locator( 'img' ) @@ -96,7 +98,6 @@ test.describe( 'Cover', () => { imageBlockUtils, } ) => { await editor.insertBlock( { name: 'core/cover' } ); - const coverBlock = page.getByRole( 'document', { name: 'Block: Cover', } ); @@ -117,10 +118,13 @@ test.describe( 'Cover', () => { const titleText = 'foo'; await editor.insertBlock( { name: 'core/cover' } ); + const coverBlock = page.getByRole( 'document', { + name: 'Block: Cover', + } ); // Choose a color swatch to transform the placeholder block into // a functioning block. - await page + await coverBlock .getByRole( 'button', { name: 'Color: Black', } ) @@ -128,28 +132,30 @@ test.describe( 'Cover', () => { // Activate the paragraph block inside the Cover block. // The name of the block differs depending on whether text has been entered or not. - const coverParagraphLocator = page.getByRole( 'document', { + const coverBlockParagraph = coverBlock.getByRole( 'document', { name: /Paragraph block|Empty block; start writing or type forward slash to choose a block/, } ); - await expect( coverParagraphLocator ).toBeEditable(); + await expect( coverBlockParagraph ).toBeEditable(); - await coverParagraphLocator.fill( titleText ); + await coverBlockParagraph.fill( titleText ); - await expect( coverParagraphLocator ).toContainText( titleText ); + await expect( coverBlockParagraph ).toContainText( titleText ); } ); test( 'can be resized using drag & drop', async ( { page, editor } ) => { await editor.insertBlock( { name: 'core/cover' } ); - - // Open the document sidebar. - await editor.openDocumentSettingsSidebar(); - - await page + const coverBlock = page.getByRole( 'document', { + name: 'Block: Cover', + } ); + await coverBlock .getByRole( 'button', { name: 'Color: Black', } ) .click(); + // Open the document sidebar. + await editor.openDocumentSettingsSidebar(); + // Open the block list viewer from the toolbar. await page .getByRole( 'toolbar', { name: 'Document tools' } ) @@ -166,28 +172,23 @@ test.describe( 'Cover', () => { .inputValue(); expect( defaultHeightValue ).toBeFalsy(); - // Establish locators for the Cover block and the resize handler. - const coverBlock = page.getByRole( 'document', { - name: 'Block: Cover', - } ); - // There is no accessible locator for this element, which is a - // bottom edge of the Cover block for resizing. + // There is no accessible locator for the draggable block resize edge, + // which is he bottom edge of the Cover block. + // Therefore a CSS selector must be used. const coverBlockResizeHandle = page.locator( '.components-resizable-box__handle-bottom' ); // Establish the existing bounding boxes for the Cover block. const coverBlockBox = await coverBlock.boundingBox(); - - expect( coverBlockBox.height ).toEqual( 450 ); + expect( coverBlockBox.height ).toBeTruthy(); // Resize the block by 100px. await coverBlockResizeHandle.hover(); await page.mouse.down(); await page.mouse.move( coverBlockBox.x, - coverBlockBox.y + coverBlockBox.height + 100, - { steps: 5 } + coverBlockBox.y + coverBlockBox.height + 100 ); await page.mouse.up(); From d6a4f4499555c768f60a9ca86ae70cc0746e1332 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Wed, 10 May 2023 18:13:20 +0900 Subject: [PATCH 11/17] - fix the import to use `import`. - add comment explaining the use of `span[aria-hidden="true"]`. --- test/e2e/specs/editor/blocks/cover.spec.js | 27 ++++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index 3d2dc3aa63dfa9..77e37741c11e62 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -2,7 +2,7 @@ * External dependencies */ import path from 'path'; -const fs = require( 'fs/promises' ); +import fs from 'fs/promises'; import os from 'os'; import { v4 as uuid } from 'uuid'; @@ -106,6 +106,9 @@ test.describe( 'Cover', () => { coverBlock.getByTestId( 'form-file-upload-input' ) ); + // The hidden span must be used as the target for opacity and color value. + // Using the Cover block to calculate the opacity results in an incorrect value of 1. + // The hidden span value returns the correct opacity at 0.5. const [ backgroundDimColor, backgroundDimOpacity ] = await getBackgroundColorAndOpacity( coverBlock.locator( 'span[aria-hidden="true"]' ) @@ -198,7 +201,7 @@ test.describe( 'Cover', () => { ); } ); - test( 'dims the background image down by 50% when transformed from the Image block', async ( { + test.only( 'dims the background image down by 50% when transformed from the Image block', async ( { page, editor, imageBlockUtils, @@ -221,17 +224,21 @@ test.describe( 'Cover', () => { await editor.transformBlockTo( 'core/cover' ); - const coverBlockBackground = page - .getByRole( 'document', { - name: 'Block: Cover', - } ) - .locator( 'span[aria-hidden="true"]' ); - - await expect( coverBlockBackground ).toBeVisible(); + const coverBlock = page.getByRole( 'document', { + name: 'Block: Cover', + } ); + // The hidden span must be used as the target for opacity and color value. + // Using the Cover block to calculate the opacity results in an incorrect value of 1. + // The hidden span value returns the correct opacity at 0.5. const [ backgroundDimColor, backgroundDimOpacity ] = - await getBackgroundColorAndOpacity( coverBlockBackground ); + await getBackgroundColorAndOpacity( + coverBlock.locator( 'span[aria-hidden="true"]' ) + ); + // The hidden span must be used as the target for opacity and color value. + // Using the Cover block to calculate the opacity results in an incorrect value of 1. + // The hidden span value returns the correct opacity at 0.5. expect( backgroundDimColor ).toBe( 'rgb(0, 0, 0)' ); expect( backgroundDimOpacity ).toBe( '0.5' ); } ); From b6e5c294eb63aa6f79bc364254f622f75aac533d Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Wed, 10 May 2023 18:27:28 +0900 Subject: [PATCH 12/17] - anchor selectors on a parent selector. --- test/e2e/specs/editor/blocks/cover.spec.js | 27 ++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index 77e37741c11e62..c882040170a50d 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -145,7 +145,10 @@ test.describe( 'Cover', () => { await expect( coverBlockParagraph ).toContainText( titleText ); } ); - test( 'can be resized using drag & drop', async ( { page, editor } ) => { + test.only( 'can be resized using drag & drop', async ( { + page, + editor, + } ) => { await editor.insertBlock( { name: 'core/cover' } ); const coverBlock = page.getByRole( 'document', { name: 'Block: Cover', @@ -159,18 +162,28 @@ test.describe( 'Cover', () => { // Open the document sidebar. await editor.openDocumentSettingsSidebar(); - // Open the block list viewer from the toolbar. + // Open the block list viewer from the Editor toolbar. await page .getByRole( 'toolbar', { name: 'Document tools' } ) .getByRole( 'button', { name: 'Document Overview' } ) .click(); - // Select the Cover block from the docuemnt overview. - await page.getByRole( 'link', { name: 'Cover' } ).click(); + // Select the Cover block from the Document Overview. + await page + .getByRole( 'region', { name: 'Document Overview' } ) + .getByRole( 'link', { name: 'Cover' } ) + .click(); + + // In the Block Editor Settings panel, click on the Styles subpanel. + const coverBlockEditorSettings = page.getByRole( 'region', { + name: 'Editor settings', + } ); + await coverBlockEditorSettings + .getByRole( 'tab', { name: 'Styles' } ) + .click(); // Ensure there the default value for the minimum height of cover is undefined. - await page.getByRole( 'tab', { name: 'Styles' } ).click(); - const defaultHeightValue = await page + const defaultHeightValue = await coverBlockEditorSettings .getByLabel( 'Minimum height of cover' ) .inputValue(); expect( defaultHeightValue ).toBeFalsy(); @@ -201,7 +214,7 @@ test.describe( 'Cover', () => { ); } ); - test.only( 'dims the background image down by 50% when transformed from the Image block', async ( { + test( 'dims the background image down by 50% when transformed from the Image block', async ( { page, editor, imageBlockUtils, From 8b19caf1f417412be22351bc0e2fed22991c1be3 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Wed, 10 May 2023 19:18:00 +0900 Subject: [PATCH 13/17] - use the Cover block's resize handle as basis for calculation when resizing the block. --- test/e2e/specs/editor/blocks/cover.spec.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index c882040170a50d..02255b7d6e2862 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -195,23 +195,29 @@ test.describe( 'Cover', () => { '.components-resizable-box__handle-bottom' ); - // Establish the existing bounding boxes for the Cover block. + // Establish the existing bounding boxes for the Cover block + // and the Cover block's resizing handle. const coverBlockBox = await coverBlock.boundingBox(); + const coverBlockResizeHandleBox = + await coverBlockResizeHandle.boundingBox(); expect( coverBlockBox.height ).toBeTruthy(); + expect( coverBlockResizeHandleBox.height ).toBeTruthy(); - // Resize the block by 100px. + // Increse the Cover block height by 100px. await coverBlockResizeHandle.hover(); await page.mouse.down(); + + // Counter-intuitively, the mouse movement calculation should not be made using the + // Cover block's bounding box, but rather based on the coordinates of the + // resize handle. await page.mouse.move( - coverBlockBox.x, - coverBlockBox.y + coverBlockBox.height + 100 + coverBlockResizeHandleBox.x + coverBlockResizeHandleBox.width / 2, + coverBlockResizeHandleBox.y + 100 ); await page.mouse.up(); const newCoverBlockBox = await coverBlock.boundingBox(); - expect( newCoverBlockBox.height ).toBeGreaterThanOrEqual( - coverBlockBox.height + 100 - ); + expect( newCoverBlockBox.height ).toBe( coverBlockBox.height + 100 ); } ); test( 'dims the background image down by 50% when transformed from the Image block', async ( { From f756edee13a9597638e7ceb311504b47dc0b13a0 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Wed, 10 May 2023 19:19:50 +0900 Subject: [PATCH 14/17] - remove testing "only" --- test/e2e/specs/editor/blocks/cover.spec.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index 02255b7d6e2862..ca3529d15df4ef 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -145,10 +145,7 @@ test.describe( 'Cover', () => { await expect( coverBlockParagraph ).toContainText( titleText ); } ); - test.only( 'can be resized using drag & drop', async ( { - page, - editor, - } ) => { + test( 'can be resized using drag & drop', async ( { page, editor } ) => { await editor.insertBlock( { name: 'core/cover' } ); const coverBlock = page.getByRole( 'document', { name: 'Block: Cover', From aadc65db9d5009e4b86d011baa31e6fcb95fda26 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Wed, 10 May 2023 19:22:44 +0900 Subject: [PATCH 15/17] - check the src repeatedly to contain the fileBasename instead. --- test/e2e/specs/editor/blocks/cover.spec.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index ca3529d15df4ef..9a7572d6a0d0cd 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -82,14 +82,8 @@ test.describe( 'Cover', () => { // beginning with `blob`. await expect( async () => { const src = await coverBlock.locator( 'img' ).getAttribute( 'src' ); - expect( src.startsWith( 'http' ) ).toBe( true ); + expect( src.includes( fileBasename ) ).toBe( true ); } ).toPass(); - - const backgroundImageURL = await coverBlock - .locator( 'img' ) - .getAttribute( 'src' ); - - expect( backgroundImageURL ).toContain( fileBasename ); } ); test( 'dims background image down by 50% by default', async ( { From 7897f28b7eaa3146eb2a023d536bc98c437eb884 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Thu, 11 May 2023 17:23:19 +0900 Subject: [PATCH 16/17] - move `getBackgroundColorAndOpacity` into the ImageBlockUtils POM. --- test/e2e/specs/editor/blocks/cover.spec.js | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index 9a7572d6a0d0cd..eefeaab9c4d3f1 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -1,10 +1,10 @@ /** * External dependencies */ -import path from 'path'; -import fs from 'fs/promises'; -import os from 'os'; -import { v4 as uuid } from 'uuid'; +const path = require( 'path' ); +const fs = require( 'fs/promises' ); +const os = require( 'os' ); +const { v4: uuid } = require( 'uuid' ); /** @typedef {import('@playwright/test').Page} Page */ @@ -13,13 +13,6 @@ import { v4 as uuid } from 'uuid'; */ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); -async function getBackgroundColorAndOpacity( locator ) { - return await locator.evaluate( ( el ) => { - const computedStyle = window.getComputedStyle( el ); - return [ computedStyle.backgroundColor, computedStyle.opacity ]; - } ); -} - test.use( { imageBlockUtils: async ( { page }, use ) => { await use( new ImageBlockUtils( { page } ) ); @@ -34,6 +27,7 @@ test.describe( 'Cover', () => { test( 'can set overlay color using color picker on block placeholder', async ( { page, editor, + imageBlockUtils, } ) => { await editor.insertBlock( { name: 'core/cover' } ); const coverBlock = page.getByRole( 'document', { @@ -47,17 +41,16 @@ test.describe( 'Cover', () => { await expect( blackColorSwatch ).toBeVisible(); // Get the RGB value of Black. - const blackRGB = await blackColorSwatch.evaluate( - ( element ) => window.getComputedStyle( element ).color + const [ blackRGB ] = await imageBlockUtils.getBackgroundColorAndOpacity( + coverBlock ); // Create the block by clicking selected color button. await blackColorSwatch.click(); // Get the RGB value of the background dim. - const actualRGB = await coverBlock.evaluate( - ( element ) => window.getComputedStyle( element ).backgroundColor - ); + const [ actualRGB ] = + await imageBlockUtils.getBackgroundColorAndOpacity( coverBlock ); expect( blackRGB ).toEqual( actualRGB ); } ); @@ -104,7 +97,7 @@ test.describe( 'Cover', () => { // Using the Cover block to calculate the opacity results in an incorrect value of 1. // The hidden span value returns the correct opacity at 0.5. const [ backgroundDimColor, backgroundDimOpacity ] = - await getBackgroundColorAndOpacity( + await imageBlockUtils.getBackgroundColorAndOpacity( coverBlock.locator( 'span[aria-hidden="true"]' ) ); expect( backgroundDimColor ).toBe( 'rgb(0, 0, 0)' ); @@ -242,7 +235,7 @@ test.describe( 'Cover', () => { // Using the Cover block to calculate the opacity results in an incorrect value of 1. // The hidden span value returns the correct opacity at 0.5. const [ backgroundDimColor, backgroundDimOpacity ] = - await getBackgroundColorAndOpacity( + await imageBlockUtils.getBackgroundColorAndOpacity( coverBlock.locator( 'span[aria-hidden="true"]' ) ); @@ -269,7 +262,7 @@ class ImageBlockUtils { ); } - async upload( inputElement ) { + async upload( locator ) { const tmpDirectory = await fs.mkdtemp( path.join( os.tmpdir(), 'gutenberg-test-image-' ) ); @@ -277,8 +270,15 @@ class ImageBlockUtils { const tmpFileName = path.join( tmpDirectory, filename + '.png' ); await fs.copyFile( this.TEST_IMAGE_FILE_PATH, tmpFileName ); - await inputElement.setInputFiles( tmpFileName ); + await locator.setInputFiles( tmpFileName ); return filename; } + + async getBackgroundColorAndOpacity( locator ) { + return await locator.evaluate( ( el ) => { + const computedStyle = window.getComputedStyle( el ); + return [ computedStyle.backgroundColor, computedStyle.opacity ]; + } ); + } } From 405c70909d0fd3944db7a518805e48256eeb8fd6 Mon Sep 17 00:00:00 2001 From: Edwin Takahashi Date: Fri, 12 May 2023 16:09:24 +0900 Subject: [PATCH 17/17] Rename POM to CoverBlockUtils --- test/e2e/specs/editor/blocks/cover.spec.js | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index eefeaab9c4d3f1..02176167813450 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -14,8 +14,8 @@ const { v4: uuid } = require( 'uuid' ); const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); test.use( { - imageBlockUtils: async ( { page }, use ) => { - await use( new ImageBlockUtils( { page } ) ); + coverBlockUtils: async ( { page }, use ) => { + await use( new CoverBlockUtils( { page } ) ); }, } ); @@ -27,7 +27,7 @@ test.describe( 'Cover', () => { test( 'can set overlay color using color picker on block placeholder', async ( { page, editor, - imageBlockUtils, + coverBlockUtils, } ) => { await editor.insertBlock( { name: 'core/cover' } ); const coverBlock = page.getByRole( 'document', { @@ -41,7 +41,7 @@ test.describe( 'Cover', () => { await expect( blackColorSwatch ).toBeVisible(); // Get the RGB value of Black. - const [ blackRGB ] = await imageBlockUtils.getBackgroundColorAndOpacity( + const [ blackRGB ] = await coverBlockUtils.getBackgroundColorAndOpacity( coverBlock ); @@ -50,7 +50,7 @@ test.describe( 'Cover', () => { // Get the RGB value of the background dim. const [ actualRGB ] = - await imageBlockUtils.getBackgroundColorAndOpacity( coverBlock ); + await coverBlockUtils.getBackgroundColorAndOpacity( coverBlock ); expect( blackRGB ).toEqual( actualRGB ); } ); @@ -58,14 +58,14 @@ test.describe( 'Cover', () => { test( 'can set background image using image upload on block placeholder', async ( { page, editor, - imageBlockUtils, + coverBlockUtils, } ) => { await editor.insertBlock( { name: 'core/cover' } ); const coverBlock = page.getByRole( 'document', { name: 'Block: Cover', } ); - const filename = await imageBlockUtils.upload( + const filename = await coverBlockUtils.upload( coverBlock.getByTestId( 'form-file-upload-input' ) ); const fileBasename = path.basename( filename ); @@ -82,14 +82,14 @@ test.describe( 'Cover', () => { test( 'dims background image down by 50% by default', async ( { page, editor, - imageBlockUtils, + coverBlockUtils, } ) => { await editor.insertBlock( { name: 'core/cover' } ); const coverBlock = page.getByRole( 'document', { name: 'Block: Cover', } ); - await imageBlockUtils.upload( + await coverBlockUtils.upload( coverBlock.getByTestId( 'form-file-upload-input' ) ); @@ -97,7 +97,7 @@ test.describe( 'Cover', () => { // Using the Cover block to calculate the opacity results in an incorrect value of 1. // The hidden span value returns the correct opacity at 0.5. const [ backgroundDimColor, backgroundDimOpacity ] = - await imageBlockUtils.getBackgroundColorAndOpacity( + await coverBlockUtils.getBackgroundColorAndOpacity( coverBlock.locator( 'span[aria-hidden="true"]' ) ); expect( backgroundDimColor ).toBe( 'rgb(0, 0, 0)' ); @@ -207,7 +207,7 @@ test.describe( 'Cover', () => { test( 'dims the background image down by 50% when transformed from the Image block', async ( { page, editor, - imageBlockUtils, + coverBlockUtils, } ) => { await editor.insertBlock( { name: 'core/image' } ); @@ -215,7 +215,7 @@ test.describe( 'Cover', () => { name: 'Block: Image', } ); - await imageBlockUtils.upload( + await coverBlockUtils.upload( imageBlock.getByTestId( 'form-file-upload-input' ) ); @@ -235,7 +235,7 @@ test.describe( 'Cover', () => { // Using the Cover block to calculate the opacity results in an incorrect value of 1. // The hidden span value returns the correct opacity at 0.5. const [ backgroundDimColor, backgroundDimOpacity ] = - await imageBlockUtils.getBackgroundColorAndOpacity( + await coverBlockUtils.getBackgroundColorAndOpacity( coverBlock.locator( 'span[aria-hidden="true"]' ) ); @@ -247,7 +247,7 @@ test.describe( 'Cover', () => { } ); } ); -class ImageBlockUtils { +class CoverBlockUtils { constructor( { page } ) { /** @type {Page} */ this.page = page;