From 47bfbbfca803c49c391cc7f60cfc08f548c83d7a Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Thu, 21 Nov 2024 11:29:38 +0300 Subject: [PATCH] Repeater e2e tests (#328) * Added e2e test for manually creating Repeater block in constructor UI * added e2e test: should render Repeater block correctly * removed the line that closes the modal help window during initial page editing in the e2e repeater test * added delay timers and modal window visibility checks for e2e repeater tests * added e2e tests for Base block controls * added tear_down usage in unit tests for proper clean up * don't add align attribute it there are no default specified * update actions deps --------- Co-authored-by: Nikita --- .github/setup-node/action.yml | 4 +- .github/workflows/deploy.yml | 2 +- .github/workflows/tests-e2e.yml | 2 +- .github/workflows/tests.yml | 8 +- classes/class-blocks.php | 4 - .../specs/editor-block-base-controls.spec.js | 213 ++++++++++++++++++ .../editor-block-repeater-control.spec.js | 160 +++++++++++++ tests/phpunit/block-render-test.php | 22 +- .../phpunit/controls/select-control-test.php | 14 +- 9 files changed, 395 insertions(+), 34 deletions(-) create mode 100644 tests/e2e/specs/editor-block-base-controls.spec.js create mode 100644 tests/e2e/specs/editor-block-repeater-control.spec.js diff --git a/.github/setup-node/action.yml b/.github/setup-node/action.yml index 928196a5e..1804b4891 100644 --- a/.github/setup-node/action.yml +++ b/.github/setup-node/action.yml @@ -10,7 +10,7 @@ runs: using: 'composite' steps: - name: Use desired version of Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' node-version: ${{ inputs.node-version }} @@ -24,7 +24,7 @@ runs: - name: Cache node_modules id: cache-node_modules - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: '**/node_modules' key: node_modules-${{ runner.os }}-${{ steps.node-version.outputs.NODE_VERSION }}-${{ hashFiles('package-lock.json') }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 86c633972..34f5602a3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -10,7 +10,7 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Disable xDebug - fixes PHP Fatal Error for `i18n make-pot` uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/tests-e2e.yml b/.github/workflows/tests-e2e.yml index ac5a18617..402b3c3ca 100644 --- a/.github/workflows/tests-e2e.yml +++ b/.github/workflows/tests-e2e.yml @@ -27,7 +27,7 @@ jobs: totalParts: [4] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Node.js and install dependencies uses: ./.github/setup-node diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 183fa9557..cf78413a6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -68,7 +68,7 @@ jobs: WP_ENV_CORE: ${{ matrix.wordpress == '' && 'WordPress/WordPress' || format( 'https://wordpress.org/wordpress-{0}.zip', needs.compute-previous-wordpress-version.outputs.previous-wordpress-version ) }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Node.js and install dependencies uses: ./.github/setup-node @@ -162,7 +162,7 @@ jobs: if: ${{ github.repository == 'nk-crew/lazy-blocks' || github.event_name == 'pull_request' }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Node.js and install dependencies uses: ./.github/setup-node @@ -181,7 +181,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up PHP uses: shivammathur/setup-php@v2 @@ -197,7 +197,7 @@ jobs: run: echo "date=$(/bin/date -u --date='last Mon' "+%F")" >> $GITHUB_OUTPUT - name: Cache PHPCS scan cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: .cache/phpcs.json key: ${{ runner.os }}-date-${{ steps.get-date.outputs.date }}-phpcs-cache-${{ hashFiles('**/composer.json', 'phpcs.xml.dist') }} diff --git a/classes/class-blocks.php b/classes/class-blocks.php index 0a1538765..ae101b72f 100644 --- a/classes/class-blocks.php +++ b/classes/class-blocks.php @@ -1206,10 +1206,6 @@ public function prepare_block_attributes( $controls, $child_of = '', $block = nu 'type' => 'string', 'default' => '', ); - $attributes['align'] = array( - 'type' => 'string', - 'default' => '', - ); $attributes['anchor'] = array( 'type' => 'string', 'default' => '', diff --git a/tests/e2e/specs/editor-block-base-controls.spec.js b/tests/e2e/specs/editor-block-base-controls.spec.js new file mode 100644 index 000000000..96bfde404 --- /dev/null +++ b/tests/e2e/specs/editor-block-base-controls.spec.js @@ -0,0 +1,213 @@ +/* eslint-disable jsdoc/no-undefined-types */ +/** + * WordPress dependencies + */ +import { test, expect } from '@wordpress/e2e-test-utils-playwright'; +import { createBlock } from '../utils/create-block'; +import { removeAllBlocks } from '../utils/remove-all-blocks'; + +test.describe('editor block with Base control', () => { + test.afterEach(async ({ requestUtils }) => { + await removeAllBlocks({ requestUtils }); + }); + + /** + * Manually add Base Block. + * + * @param {Page} page Provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. + * @param {Editor} editor End to end test utilities for the WordPress Block Editor. + * @param {Admin} admin End to end test utilities for WordPress admin’s user interface. + * @param {RequestUtils} requestUtils Playwright utilities for interacting with the WordPress REST API. + * @return {number} blockID Block ID. + */ + async function manuallyAddBaseBlock(page, editor, admin, requestUtils) { + const blockID = await createBlock({ + requestUtils, + title: 'Test Base Block', + slug: 'test-base-block', + code: '

Test text control is:

Test select control label is:

Test select control value is:

The checkbox test control is True

The checkbox test control is False

', + codeSingleOutput: true, + }); + + await admin.visitAdminPage('edit.php?post_type=lazyblocks'); + + await page.getByLabel('“Test Base Block” (Edit)').click(); + + await page.waitForTimeout(500); + + const closeModal = await page + .locator('.components-modal__header') + .getByRole('button', { name: 'Close' }); + + await page.waitForTimeout(500); + + if (await closeModal.isVisible()) { + await closeModal.click(); + } + + // Generate Text control + await editor.canvas + .getByLabel('Inspector Controls') + .getByRole('button') + .click(); + + await editor.canvas.getByText('(no label)').click(); + + await page.getByLabel('Label').fill('Test Text Control'); + + await page.getByLabel('Type').click(); + + await page.getByRole('button', { name: 'Text', exact: true }).click(); + + // Generate Select control + await editor.canvas + .getByLabel('Inspector Controls') + .locator('button.lzb-constructor-controls-item-appender') + .click(); + + await editor.canvas.getByText('(no label)').click(); + + await page.getByLabel('Label').fill('Test Select Control'); + + await page.getByLabel('Type').click(); + + await page.getByRole('button', { name: 'Select' }).click(); + + await page.getByRole('button', { name: '+ Add Choice' }).click(); + await page.getByPlaceholder('Label').fill('First Selector Choice'); + await page.getByPlaceholder('Value').fill('first'); + await page.getByRole('button', { name: '+ Add Choice' }).click(); + + await page + .getByPlaceholder('Label') + .nth(1) + .fill('Second Selector Choice'); + + await page.getByPlaceholder('Value').nth(1).fill('second'); + + await page.getByLabel('Both (Array)').check(); + + // Generate Checkbox control + await editor.canvas + .getByLabel('Inspector Controls') + .locator('button.lzb-constructor-controls-item-appender') + .click(); + + await editor.canvas.getByText('(no label)').click(); + + await page.getByLabel('Label').fill('Test Checkbox Control'); + await page.getByLabel('Type').click(); + await page.getByRole('button', { name: 'Checkbox' }).click(); + await page + .locator('#lazyblocks-control-checkbox-checked') + .nth(1) + .check(); + + await editor.canvas.getByLabel('PHP').click(); + + // Publish post. + await page.locator('role=button[name="Save"i]').click(); + + await expect(page.locator('role=button[name="Save"i]')).toBeDisabled(); + + return blockID; + } + + test('create Base block manually in constructor UI', async ({ + page, + editor, + admin, + requestUtils, + }) => { + const blockID = await manuallyAddBaseBlock( + page, + editor, + admin, + requestUtils + ); + // Check for this block in the lazyblocks posts list admin. + await admin.visitAdminPage('edit.php?post_type=lazyblocks'); + + await expect(page.locator(`#post-${blockID}`)).toBeVisible(); + }); + + test('should render Base block correctly', async ({ + page, + editor, + admin, + requestUtils, + }) => { + await manuallyAddBaseBlock(page, editor, admin, requestUtils); + + await admin.createNewPost(); + + await editor.insertBlock({ + name: 'lazyblock/test-base-block', + }); + + await page.getByLabel('Test Text Control').fill('Just a text'); + + await page.getByLabel('Test Select Control').selectOption('second'); + + await page + .locator( + 'input[type="checkbox"].components-checkbox-control__input' + ) + .uncheck(); + + // Backend render. + await expect( + editor.canvas + .locator('.lzb-preview-server') + .getByText('Test text control is: Just a text') + ).toBeVisible(); + + await expect( + editor.canvas + .locator('.lzb-preview-server') + .getByText( + 'Test select control label is: Second Selector Choice' + ) + ).toBeVisible(); + + await expect( + editor.canvas + .locator('.lzb-preview-server') + .getByText('Test select control value is: second') + ).toBeVisible(); + + await expect( + editor.canvas + .locator('.lzb-preview-server') + .getByText('The checkbox test control is False') + ).toBeVisible(); + + await page + .getByRole('button', { name: 'Publish', exact: true }) + .click(); + await page + .getByLabel('Editor publish') + .getByRole('button', { name: 'Publish', exact: true }) + .click(); + await page + .getByLabel('Editor publish') + .getByRole('link', { name: 'View Post' }) + .click(); + + // Frontend render. + await expect( + page.getByText('Test text control is: Just a text') + ).toBeVisible(); + await expect( + page.getByText( + 'Test select control label is: Second Selector Choice' + ) + ).toBeVisible(); + await expect( + page.getByText('Test select control value is: second') + ).toBeVisible(); + await expect( + page.getByText('The checkbox test control is False') + ).toBeVisible(); + }); +}); diff --git a/tests/e2e/specs/editor-block-repeater-control.spec.js b/tests/e2e/specs/editor-block-repeater-control.spec.js new file mode 100644 index 000000000..12e39148d --- /dev/null +++ b/tests/e2e/specs/editor-block-repeater-control.spec.js @@ -0,0 +1,160 @@ +/* eslint-disable jsdoc/no-undefined-types */ +/** + * WordPress dependencies + */ +import { test, expect } from '@wordpress/e2e-test-utils-playwright'; +import { createBlock } from '../utils/create-block'; +import { removeAllBlocks } from '../utils/remove-all-blocks'; + +test.describe('editor block with Repeater control', () => { + test.afterEach(async ({ requestUtils }) => { + await removeAllBlocks({ requestUtils }); + }); + + /** + * Manually add Repeater Block. + * + * @param {Page} page Provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. + * @param {Editor} editor End to end test utilities for the WordPress Block Editor. + * @param {Admin} admin End to end test utilities for WordPress admin’s user interface. + * @param {RequestUtils} requestUtils Playwright utilities for interacting with the WordPress REST API. + * @return {number} blockID Block ID. + */ + async function manuallyAddRepeaterBlock(page, editor, admin, requestUtils) { + const blockID = await createBlock({ + requestUtils, + title: 'Test Repeater Block', + slug: 'test-repeater-block', + code: '

', + codeSingleOutput: true, + }); + + await admin.visitAdminPage('edit.php?post_type=lazyblocks'); + + await page.getByLabel('“Test Repeater Block” (Edit)').click(); + + await page.waitForTimeout(500); + + const closeModal = await page + .locator('.components-modal__header') + .getByRole('button', { name: 'Close' }); + + await page.waitForTimeout(500); + + if (await closeModal.isVisible()) { + await closeModal.click(); + } + + await editor.canvas + .getByLabel('Inspector Controls') + .getByRole('button') + .click(); + + await editor.canvas.getByText('(no label)').click(); + + await page.getByLabel('Label').fill('Test Repeater Control'); + + await page.getByLabel('Type').click(); + + await page.getByRole('button', { name: 'Repeater' }).click(); + + await editor.canvas + .getByRole('button', { name: 'Show Child Controls' }) + .click(); + + await editor.canvas + .locator('.lzb-constructor-controls-item-appender') + .first() + .click(); + + await editor.canvas.getByText('(no label)').click(); + + await page.getByLabel('Label').fill('Text control nested in repeater'); + + await page.getByLabel('Type').click(); + + await page.getByRole('button', { name: 'Text', exact: true }).click(); + + await editor.canvas.getByLabel('PHP').click(); + + // Publish post. + await page.locator('role=button[name="Save"i]').click(); + + await expect(page.locator('role=button[name="Save"i]')).toBeDisabled(); + + return blockID; + } + + test('create Repeater block manually in constructor UI', async ({ + page, + editor, + admin, + requestUtils, + }) => { + const blockID = await manuallyAddRepeaterBlock( + page, + editor, + admin, + requestUtils + ); + // Check for this block in the lazyblocks posts list admin. + await admin.visitAdminPage('edit.php?post_type=lazyblocks'); + + await expect(page.locator(`#post-${blockID}`)).toBeVisible(); + }); + + test('should render Repeater block correctly', async ({ + page, + editor, + admin, + requestUtils, + }) => { + await manuallyAddRepeaterBlock(page, editor, admin, requestUtils); + + await admin.createNewPost(); + + await editor.insertBlock({ + name: 'lazyblock/test-repeater-block', + }); + + await page.getByRole('button', { name: '+ Add Row' }).click(); + await page.getByLabel('Text control nested in').click(); + await page.getByLabel('Text control nested in').fill('Test Row 1'); + await page.getByRole('button', { name: '+ Add Row' }).click(); + await page.getByLabel('Text control nested in').click(); + await page.getByLabel('Text control nested in').fill('Test Row 2'); + await page.getByRole('button', { name: '+ Add Row' }).click(); + await page.getByLabel('Text control nested in').click(); + await page.getByLabel('Text control nested in').fill('Test Row 3'); + + // Backend render. + await expect( + editor.canvas.locator('.lzb-preview-server').getByText('Test Row 1') + ).toBeVisible(); + + await expect( + editor.canvas.locator('.lzb-preview-server').getByText('Test Row 2') + ).toBeVisible(); + + await expect( + editor.canvas.locator('.lzb-preview-server').getByText('Test Row 3') + ).toBeVisible(); + + await page + .getByRole('button', { name: 'Publish', exact: true }) + .click(); + await page + .getByLabel('Editor publish') + .getByRole('button', { name: 'Publish', exact: true }) + .click(); + await page + .getByLabel('Editor publish') + .getByRole('link', { name: 'View Post' }) + .click(); + + // Frontend render. + await expect(page.getByText('Test Row 1')).toBeVisible(); + await expect(page.getByText('Test Row 2')).toBeVisible(); + await expect(page.getByText('Test Row 3')).toBeVisible(); + }); +}); diff --git a/tests/phpunit/block-render-test.php b/tests/phpunit/block-render-test.php index 8609c1eda..0c065a26b 100644 --- a/tests/phpunit/block-render-test.php +++ b/tests/phpunit/block-render-test.php @@ -6,9 +6,6 @@ public function add_test_block( $attrs = array() ) { lazyblocks()->add_block( array_merge( array( 'slug' => $block_slug, - 'supports' => array( - 'align' => false, - ), ), $attrs ) ); @@ -27,6 +24,13 @@ public function remove_test_block() { lazyblocks()->blocks()->remove_block( $block_slug ); } + // Remove test block after each test. + public function tear_down() { + $this->remove_test_block(); + + parent::tear_down(); + } + public function test_simple_block_render() { $this->add_test_block( array( 'code' => array( @@ -38,8 +42,6 @@ public function test_simple_block_render() { '

Test

', do_blocks( '' ) ); - - $this->remove_test_block(); } public function test_empty_block_render() { @@ -54,8 +56,6 @@ public function test_empty_block_render() { '', do_blocks( '' ) ); - - $this->remove_test_block(); } public function test_block_render_attributes() { @@ -73,8 +73,6 @@ public function test_block_render_attributes() { '

Test

', do_blocks( '' ) ); - - $this->remove_test_block(); } public function test_block_render_controls() { @@ -94,8 +92,6 @@ public function test_block_render_controls() { '

text control val

', do_blocks( '' ) ); - - $this->remove_test_block(); } public function test_block_render_inner_blocks_component() { @@ -193,8 +189,6 @@ public function test_block_render_inner_blocks_component() { ) ); - $this->remove_test_block(); - remove_filter( 'lzb/block_render/allow_inner_blocks_wrapper', '__return_false' ); } @@ -223,7 +217,5 @@ public function test_block_render_deprecated_inner_blocks_control() { '' ) ); - - $this->remove_test_block(); } } diff --git a/tests/phpunit/controls/select-control-test.php b/tests/phpunit/controls/select-control-test.php index 9e5a4ebe4..6cf048030 100644 --- a/tests/phpunit/controls/select-control-test.php +++ b/tests/phpunit/controls/select-control-test.php @@ -6,9 +6,6 @@ public function add_test_block( $attrs = array() ) { lazyblocks()->add_block( array_merge( array( 'slug' => $block_slug, - 'supports' => array( - 'align' => false, - ), ), $attrs ) ); @@ -27,6 +24,13 @@ public function remove_test_block() { lazyblocks()->blocks()->remove_block( $block_slug ); } + // Remove test block after each test. + public function tear_down() { + $this->remove_test_block(); + + parent::tear_down(); + } + public function test_single_value() { $this->add_test_block( array( 'controls' => array( @@ -67,8 +71,6 @@ public function test_single_value() { '', do_blocks( '' ) ); - - $this->remove_test_block(); } public function test_multiple_value() { @@ -125,7 +127,5 @@ public function test_multiple_value() { '', do_blocks( '' ) ); - - $this->remove_test_block(); } }