From 51c726ca6eb64bcfd22ca3fe40441bb6a880fff4 Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Tue, 19 Nov 2024 18:41:52 +0300 Subject: [PATCH 1/8] Added e2e test for manually creating Repeater block in constructor UI --- .../editor-block-repeater-control.spec.js | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 tests/e2e/specs/editor-block-repeater-control.spec.js 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 00000000..4ff26feb --- /dev/null +++ b/tests/e2e/specs/editor-block-repeater-control.spec.js @@ -0,0 +1,75 @@ +/** + * 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 }); + }); + + test('create Repeater block manually in constructor UI', async ({ + 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.getByLabel('Close', { exact: true }).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(); + + // 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(); + }); +}); From 8dbeea77c26b3c454ab58c7e99277fb6833b1654 Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Wed, 20 Nov 2024 13:33:18 +0300 Subject: [PATCH 2/8] added e2e test: should render Repeater block correctly --- .../editor-block-repeater-control.spec.js | 87 +++++++++++++++++-- 1 file changed, 81 insertions(+), 6 deletions(-) diff --git a/tests/e2e/specs/editor-block-repeater-control.spec.js b/tests/e2e/specs/editor-block-repeater-control.spec.js index 4ff26feb..6246bca1 100644 --- a/tests/e2e/specs/editor-block-repeater-control.spec.js +++ b/tests/e2e/specs/editor-block-repeater-control.spec.js @@ -1,3 +1,4 @@ +/* eslint-disable jsdoc/no-undefined-types */ /** * WordPress dependencies */ @@ -10,12 +11,16 @@ test.describe('editor block with Repeater control', () => { await removeAllBlocks({ requestUtils }); }); - test('create Repeater block manually in constructor UI', async ({ - page, - editor, - admin, - 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', @@ -67,9 +72,79 @@ test.describe('editor block with Repeater control', () => { 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(); + }); }); From e7104e012e2c3308a4e8278c6f456bb4cabf63d9 Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Wed, 20 Nov 2024 13:42:37 +0300 Subject: [PATCH 3/8] removed the line that closes the modal help window during initial page editing in the e2e repeater test --- tests/e2e/specs/editor-block-repeater-control.spec.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/e2e/specs/editor-block-repeater-control.spec.js b/tests/e2e/specs/editor-block-repeater-control.spec.js index 6246bca1..2db5e062 100644 --- a/tests/e2e/specs/editor-block-repeater-control.spec.js +++ b/tests/e2e/specs/editor-block-repeater-control.spec.js @@ -33,8 +33,6 @@ test.describe('editor block with Repeater control', () => { await page.getByLabel('“Test Repeater Block” (Edit)').click(); - await page.getByLabel('Close', { exact: true }).click(); - await editor.canvas .getByLabel('Inspector Controls') .getByRole('button') From eebe4495215f33a6b9a7256280f009c2a1c785ee Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Wed, 20 Nov 2024 15:31:19 +0300 Subject: [PATCH 4/8] added delay timers and modal window visibility checks for e2e repeater tests --- .../e2e/specs/editor-block-repeater-control.spec.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/e2e/specs/editor-block-repeater-control.spec.js b/tests/e2e/specs/editor-block-repeater-control.spec.js index 2db5e062..12e39148 100644 --- a/tests/e2e/specs/editor-block-repeater-control.spec.js +++ b/tests/e2e/specs/editor-block-repeater-control.spec.js @@ -33,6 +33,18 @@ test.describe('editor block with Repeater control', () => { 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') From 3b203197ac843eaa25da79e9e48f2b04d61b7fe6 Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Wed, 20 Nov 2024 17:28:55 +0300 Subject: [PATCH 5/8] added e2e tests for Base block controls --- .../specs/editor-block-base-controls.spec.js | 213 ++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 tests/e2e/specs/editor-block-base-controls.spec.js 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 00000000..96bfde40 --- /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(); + }); +}); From a1e40f1b30ae9f7860a295b0c975663e01bfe51d Mon Sep 17 00:00:00 2001 From: Nikita Date: Thu, 21 Nov 2024 11:08:11 +0300 Subject: [PATCH 6/8] added tear_down usage in unit tests for proper clean up --- tests/phpunit/block-render-test.php | 19 +++++++------------ .../phpunit/controls/select-control-test.php | 11 +++++++---- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/tests/phpunit/block-render-test.php b/tests/phpunit/block-render-test.php index 8609c1ed..f868f294 100644 --- a/tests/phpunit/block-render-test.php +++ b/tests/phpunit/block-render-test.php @@ -27,6 +27,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 +45,6 @@ public function test_simple_block_render() { '

Test

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

Test

', do_blocks( '' ) ); - - $this->remove_test_block(); } public function test_block_render_controls() { @@ -94,8 +95,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 +192,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 +220,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 9e5a4ebe..df6134d9 100644 --- a/tests/phpunit/controls/select-control-test.php +++ b/tests/phpunit/controls/select-control-test.php @@ -27,6 +27,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 +74,6 @@ public function test_single_value() { '', do_blocks( '' ) ); - - $this->remove_test_block(); } public function test_multiple_value() { @@ -125,7 +130,5 @@ public function test_multiple_value() { '', do_blocks( '' ) ); - - $this->remove_test_block(); } } From 3e5de748a26d794f59bd99c6527d168a81273312 Mon Sep 17 00:00:00 2001 From: Nikita Date: Thu, 21 Nov 2024 11:18:14 +0300 Subject: [PATCH 7/8] don't add align attribute it there are no default specified --- classes/class-blocks.php | 4 ---- tests/phpunit/block-render-test.php | 3 --- tests/phpunit/controls/select-control-test.php | 3 --- 3 files changed, 10 deletions(-) diff --git a/classes/class-blocks.php b/classes/class-blocks.php index 0a153876..ae101b72 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/phpunit/block-render-test.php b/tests/phpunit/block-render-test.php index f868f294..0c065a26 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 ) ); diff --git a/tests/phpunit/controls/select-control-test.php b/tests/phpunit/controls/select-control-test.php index df6134d9..6cf04803 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 ) ); From c3d5f34515914f81b14aa76f1f4142bced23f67c Mon Sep 17 00:00:00 2001 From: Nikita Date: Thu, 21 Nov 2024 11:23:15 +0300 Subject: [PATCH 8/8] update actions deps --- .github/setup-node/action.yml | 4 ++-- .github/workflows/deploy.yml | 2 +- .github/workflows/tests-e2e.yml | 2 +- .github/workflows/tests.yml | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/setup-node/action.yml b/.github/setup-node/action.yml index 928196a5..1804b489 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 86c63397..34f5602a 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 ac5a1861..402b3c3c 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 183fa955..cf78413a 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') }}