From 2046d80927c72187ab76b2b87150ad4de815bb27 Mon Sep 17 00:00:00 2001 From: Evan Herman Date: Thu, 25 Jul 2024 15:18:28 -0400 Subject: [PATCH] Escape the HTML in the editor of the posts and post carousel blocks (#2618) * Start work to support WP 6.6 in the tests * Extract sidebar class * Escape the HTML in the editor of the posts and post carousel blocks * Bump PHP unit to use WordPress 6.6 * Add 6.6 to e2e tests * Fix selector of e2e helper savePage() --------- Co-authored-by: Olivier Lafleur --- .dev/tests/cypress/helpers.js | 29 ++++++++++++------- .github/workflows/test-e2e.yml | 2 +- .github/workflows/test-php.yml | 2 +- package.json | 1 + src/blocks/features/test/features.cypress.js | 6 ++-- src/blocks/form/test/form.cypress.js | 4 +-- src/blocks/gif/test/gif.cypress.js | 2 +- src/blocks/hero/test/hero.cypress.js | 2 +- src/blocks/post-carousel/post-item.js | 3 +- .../test/post-carousel.cypress.js | 4 +-- src/blocks/posts/edit.js | 5 ++-- src/blocks/posts/test/posts.cypress.js | 4 +-- .../test/pricing-table-item.cypress.js | 6 +--- src/blocks/row/test/row.cypress.js | 2 +- .../services/service/test/service.cypress.js | 4 +-- .../test/shape-divider.cypress.js | 4 +-- yarn.lock | 7 +++++ 17 files changed, 50 insertions(+), 37 deletions(-) diff --git a/.dev/tests/cypress/helpers.js b/.dev/tests/cypress/helpers.js index 94f485ba607..a13da295d7a 100644 --- a/.dev/tests/cypress/helpers.js +++ b/.dev/tests/cypress/helpers.js @@ -2,7 +2,7 @@ * Returns true if styles tab exists false otherwise. */ export function selectStylesTabIfExists() { - cy.get( '.edit-post-sidebar' ).find( 'button[aria-label="Styles"]' ).click(); + cy.get( sidebarClass() ).find( 'button[aria-label="Styles"]' ).click(); } /** @@ -172,7 +172,11 @@ export function addNewGroupToPost() { * From inside the WordPress editor open the CoBlocks Gutenberg editor panel */ export function savePage() { - cy.get( '.edit-post-header__settings button.is-primary' ).click(); + if ( isWP66AtLeast() ) { + cy.get( '.editor-header__settings button.is-primary' ).click(); + } else { + cy.get( '.edit-post-header__settings button.is-primary' ).click(); + } cy.get( '.components-editor-notices__snackbar', { timeout: 120000 } ).should( 'not.be.empty' ); @@ -263,7 +267,7 @@ export function getBlockSlug() { export function setBlockStyle( style ) { openSettingsPanel( RegExp( 'styles', 'i' ) ); - cy.get( '.edit-post-sidebar [class*="editor-block-styles"]' ) + cy.get( sidebarClass() + ' [class*="editor-block-styles"]' ) .contains( RegExp( style, 'i' ) ) .click(); } @@ -276,7 +280,7 @@ export function setBlockStyle( style ) { export function setNewBlockStyle( style ) { selectStylesTabIfExists(); - cy.get( '.edit-post-sidebar [class*="editor-block-styles"]' ) + cy.get( sidebarClass() + ' [class*="editor-block-styles"]' ) .contains( RegExp( style, 'i' ) ) .click(); } @@ -350,7 +354,7 @@ export function setBlockAlignment( alignment ) { export function setInputValue( panelName, settingName, value, ignoreCase = true ) { openSettingsPanel( ignoreCase ? RegExp( panelName, 'i' ) : panelName ); - cy.get( '.edit-post-sidebar' ) + cy.get( sidebarClass() ) .contains( ignoreCase ? RegExp( settingName, 'i' ) : settingName ).not( '.block-editor-block-card__description' ) .then( ( $settingSection ) => { cy.get( Cypress.$( $settingSection ).parent() ) @@ -557,7 +561,7 @@ export function addCustomBlockClass( classes, blockID = '' ) { } } ); - cy.get( 'div.edit-post-sidebar' ) + cy.get( 'div' + sidebarClass() ) .contains( /Additional CSS/i ) .next( 'input' ) .then( ( $inputElem ) => { @@ -612,15 +616,14 @@ export function isNotWPLocalEnv() { return Cypress.env( 'testURL' ) !== 'http://localhost:8889'; } -// A condition to determine if we are testing on WordPress 6.4+ -export function isWP64AtLeast() { - return Cypress.$( "[class*='branch-6-4']" ).length > 0 || Cypress.$( "[class*='branch-6-5']" ).length > 0; -} - export function isWP65AtLeast() { return Cypress.$( "[class*='branch-6-5']" ).length > 0 || Cypress.$( "[class*='branch-6-6']" ).length > 0; } +export function isWP66AtLeast() { + return Cypress.$( "[class*='branch-6-6']" ).length > 0 || Cypress.$( "[class*='branch-6-7']" ).length > 0; +} + function getIframeDocument( containerClass ) { return cy.get( containerClass + ' iframe' ).its( '0.contentDocument' ).should( 'exist' ); } @@ -631,3 +634,7 @@ export function getIframeBody( containerClass ) { // chaining more Cypress commands, like ".find(...)" .then( cy.wrap ); } + +export const sidebarClass = () => { + return isWP66AtLeast() ? '.editor-sidebar__panel' : '.edit-post-sidebar'; +}; diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index e12541a9cea..ba65fa7e6b7 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -22,9 +22,9 @@ jobs: fail-fast: false matrix: wp: # Test against Prev-Prev Major, Prev-Major, and current Major release versions. - - "6.3" - "6.4" - "6.5" + - "6.6" theme: - "https://downloads.wordpress.org/theme/go.zip" - "" # Default theme is TwentyTwentyThree diff --git a/.github/workflows/test-php.yml b/.github/workflows/test-php.yml index 86f9553de50..b761b29e1d9 100644 --- a/.github/workflows/test-php.yml +++ b/.github/workflows/test-php.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: php: ['7.4','8.3'] - wp: ['6.4'] # TODO: Add 6.6 when released + wp: ['6.6'] name: PHP Unit ${{ matrix.php }} | WP Version ${{ matrix.wp }} uses: ./.github/workflows/test-php-unit.yml with: diff --git a/package.json b/package.json index 5aed1d7d896..d3abbc6a5e8 100644 --- a/package.json +++ b/package.json @@ -119,6 +119,7 @@ "@wordpress/editor": "^13.21.0", "@wordpress/element": "^5.21.0", "@wordpress/env": "^10.1.0", + "@wordpress/escape-html": "^3.4.0", "@wordpress/eslint-plugin": "^17.1.0", "@wordpress/hooks": "^3.44.0", "@wordpress/i18n": "^4.44.0", diff --git a/src/blocks/features/test/features.cypress.js b/src/blocks/features/test/features.cypress.js index ef94fdb6690..13cad3e6af9 100644 --- a/src/blocks/features/test/features.cypress.js +++ b/src/blocks/features/test/features.cypress.js @@ -43,15 +43,15 @@ describe( 'Test CoBlocks Features Block', function() { cy.get( '.wp-block-coblocks-feature' ).should( 'have.length', 2 ); - cy.get( '.edit-post-sidebar' ).find( 'input[aria-label="Columns"][type="number"]' ).focus().type( '{selectall}' ).type( 1 ); + cy.get( helpers.sidebarClass() ).find( 'input[aria-label="Columns"][type="number"]' ).focus().type( '{selectall}' ).type( 1 ); cy.get( '.wp-block-coblocks-feature' ).should( 'have.length', 2 ); // Children should never decrease with column count - cy.get( '.edit-post-sidebar' ).find( 'input[aria-label="Columns"][type="number"]' ).focus().type( '{selectall}' ).type( 3 ); + cy.get( helpers.sidebarClass() ).find( 'input[aria-label="Columns"][type="number"]' ).focus().type( '{selectall}' ).type( 3 ); cy.get( '.wp-block-coblocks-feature' ).should( 'have.length', 3 ); - cy.get( '.edit-post-sidebar' ).find( 'input[aria-label="Columns"][type="number"]' ).focus().type( '{selectall}' ).type( 4 ); + cy.get( helpers.sidebarClass() ).find( 'input[aria-label="Columns"][type="number"]' ).focus().type( '{selectall}' ).type( 4 ); cy.get( '.wp-block-coblocks-feature' ).should( 'have.length', 4 ); diff --git a/src/blocks/form/test/form.cypress.js b/src/blocks/form/test/form.cypress.js index b678917ce2d..a4c8d958cd5 100644 --- a/src/blocks/form/test/form.cypress.js +++ b/src/blocks/form/test/form.cypress.js @@ -401,7 +401,7 @@ describe( 'Test CoBlocks Form Block', function() { cy.get( '[data-type="coblocks/form"]' ) .click( { force: true } ); - cy.get( 'div.edit-post-sidebar' ) + cy.get( 'div' + helpers.sidebarClass() ) .contains( /Subject/i ) .next( 'input' ) .then( ( $inputElem ) => { @@ -479,7 +479,7 @@ describe( 'Test CoBlocks Form Block', function() { cy.get( '[data-type="coblocks/form"]' ) .click( { force: true } ); - cy.get( 'div.edit-post-sidebar' ) + cy.get( 'div' + helpers.sidebarClass() ) .contains( /Success Message/i ) .next( 'textarea' ) .then( ( $inputElem ) => { diff --git a/src/blocks/gif/test/gif.cypress.js b/src/blocks/gif/test/gif.cypress.js index 6dea73bcc8e..57eff712883 100644 --- a/src/blocks/gif/test/gif.cypress.js +++ b/src/blocks/gif/test/gif.cypress.js @@ -42,7 +42,7 @@ describe( 'Test CoBlocks Gif Block', function() { cy.get( '.wp-block-coblocks-gif' ).find( 'img' ).should( 'have.length', 1 ); - cy.get( '.edit-post-sidebar' ).contains( /Alt text/ ).parent().find( 'textarea' ).type( gifText ); + cy.get( helpers.sidebarClass() ).contains( /Alt text/ ).parent().find( 'textarea' ).type( gifText ); helpers.savePage(); diff --git a/src/blocks/hero/test/hero.cypress.js b/src/blocks/hero/test/hero.cypress.js index 1b593faf6fe..f09564c2581 100644 --- a/src/blocks/hero/test/hero.cypress.js +++ b/src/blocks/hero/test/hero.cypress.js @@ -75,7 +75,7 @@ describe( 'Test CoBlocks Hero Block', function() { cy.get( '.wp-block-coblocks-hero' ).find( '.is-fullscreen' ).should( 'exist' ); - cy.get( '.edit-post-sidebar' ).find( 'div[aria-label="Select layout"]' ).children().each( ( $layoutButton ) => { + cy.get( helpers.sidebarClass() ).find( 'div[aria-label="Select layout"]' ).children().each( ( $layoutButton ) => { cy.get( $layoutButton ).click(); } ); diff --git a/src/blocks/post-carousel/post-item.js b/src/blocks/post-carousel/post-item.js index 4e7cee920dc..aeca2fe43c8 100644 --- a/src/blocks/post-carousel/post-item.js +++ b/src/blocks/post-carousel/post-item.js @@ -13,6 +13,7 @@ import { } from '@wordpress/components'; import { PlainText } from '@wordpress/block-editor'; import { RawHTML } from '@wordpress/element'; +import { escapeHTML } from '@wordpress/escape-html'; import { withSelect } from '@wordpress/data'; // Disable reason: We choose to use unsafe APIs in our codebase. // eslint-disable-next-line @wordpress/no-unsafe-wp-apis @@ -78,7 +79,7 @@ const PostItem = ( { - { excerpt.trim().split( ' ', excerptLength ).join( ' ' ) } + { escapeHTML( excerpt.trim().split( ' ', excerptLength ).join( ' ' ) ) } } diff --git a/src/blocks/post-carousel/test/post-carousel.cypress.js b/src/blocks/post-carousel/test/post-carousel.cypress.js index 1054ad0a635..e1b958840a5 100644 --- a/src/blocks/post-carousel/test/post-carousel.cypress.js +++ b/src/blocks/post-carousel/test/post-carousel.cypress.js @@ -57,9 +57,9 @@ describe( 'Test CoBlocks Post Carousel Block', function() { it( 'Test the post-carousel block custom classes.', function() { helpers.addBlockToPost( 'coblocks/post-carousel', true ); - cy.get( '.edit-post-sidebar' ).contains( /post carousel settings/i ).click( { force: true } ); + cy.get( helpers.sidebarClass() ).contains( /post carousel settings/i ).click( { force: true } ); - cy.get( '.edit-post-sidebar' ).contains( /feed settings/i ).click( { force: true } ); + cy.get( helpers.sidebarClass() ).contains( /feed settings/i ).click( { force: true } ); helpers.addCustomBlockClass( 'my-custom-class', 'post-carousel' ); diff --git a/src/blocks/posts/edit.js b/src/blocks/posts/edit.js index 9ba6c6dcafa..abf08c9691e 100755 --- a/src/blocks/posts/edit.js +++ b/src/blocks/posts/edit.js @@ -13,6 +13,7 @@ import apiFetch from '@wordpress/api-fetch'; import { __ } from '@wordpress/i18n'; import { compose, usePrevious } from '@wordpress/compose'; import { lazy, RawHTML, useState, useEffect, useRef } from '@wordpress/element'; +import { escapeHTML } from '@wordpress/escape-html'; import { addQueryArgs } from '@wordpress/url'; // Disable reason: We choose to use unsafe APIs in our codebase. // eslint-disable-next-line @wordpress/no-unsafe-wp-apis @@ -435,8 +436,8 @@ const PostsEdit = ( props ) => { key="html" > { excerptLength < excerpt.trim().split( ' ' ).length - ? excerpt.trim().split( ' ', excerptLength ).join( ' ' ) + '…' - : excerpt.trim().split( ' ', excerptLength ).join( ' ' ) } + ? escapeHTML( excerpt.trim().split( ' ', excerptLength ).join( ' ' ) ) + '…' + : escapeHTML( excerpt.trim().split( ' ', excerptLength ).join( ' ' ) ) } } diff --git a/src/blocks/posts/test/posts.cypress.js b/src/blocks/posts/test/posts.cypress.js index 3b543df6e64..9054ce15520 100644 --- a/src/blocks/posts/test/posts.cypress.js +++ b/src/blocks/posts/test/posts.cypress.js @@ -74,9 +74,9 @@ describe( 'Test CoBlocks Posts Block', function() { it( 'Test posts block custom classes.', function() { helpers.addBlockToPost( 'coblocks/posts', true ); - cy.get( '.edit-post-sidebar' ).contains( /posts settings/i ).click( { force: true } ); + cy.get( helpers.sidebarClass() ).contains( /posts settings/i ).click( { force: true } ); - cy.get( '.edit-post-sidebar' ).contains( /feed settings/i ).click( { force: true } ); + cy.get( helpers.sidebarClass() ).contains( /feed settings/i ).click( { force: true } ); helpers.addCustomBlockClass( 'my-custom-class', 'posts' ); diff --git a/src/blocks/pricing-table/pricing-table-item/test/pricing-table-item.cypress.js b/src/blocks/pricing-table/pricing-table-item/test/pricing-table-item.cypress.js index c05a79b0d90..8a765c451a3 100644 --- a/src/blocks/pricing-table/pricing-table-item/test/pricing-table-item.cypress.js +++ b/src/blocks/pricing-table/pricing-table-item/test/pricing-table-item.cypress.js @@ -71,11 +71,7 @@ describe( 'Test CoBlocks Pricing Table Item Block', function() { featuresText = ' ' + featuresText; - if ( helpers.isWP64AtLeast() ) { - firstTableItem().find( '.wp-block-coblocks-pricing-table-item__features' ).should( 'have.text', featuresText ); - } else { - firstTableItem().find( '.wp-block-coblocks-pricing-table-item__features > li' ).should( 'have.text', featuresText ); - } + firstTableItem().find( '.wp-block-coblocks-pricing-table-item__features' ).should( 'have.text', featuresText ); firstTableItem().find( '.wp-block-button' ).should( 'have.text', buttonText ); } ); diff --git a/src/blocks/row/test/row.cypress.js b/src/blocks/row/test/row.cypress.js index 9e564e554a5..de2137f6032 100644 --- a/src/blocks/row/test/row.cypress.js +++ b/src/blocks/row/test/row.cypress.js @@ -104,7 +104,7 @@ describe( 'Test CoBlocks Row Block', function() { cy.get( '.wp-block-coblocks-row' ).click( { force: true } ); - cy.get( '.edit-post-sidebar' ).contains( /row settings/i ).click(); + cy.get( helpers.sidebarClass() ).contains( /row settings/i ).click(); helpers.addCustomBlockClass( 'my-custom-class', 'row' ); diff --git a/src/blocks/services/service/test/service.cypress.js b/src/blocks/services/service/test/service.cypress.js index 207d2fca131..0edae5ad2aa 100644 --- a/src/blocks/services/service/test/service.cypress.js +++ b/src/blocks/services/service/test/service.cypress.js @@ -40,7 +40,7 @@ describe( 'Test CoBlocks Service Block', function() { } } ); - cy.get( 'div.edit-post-sidebar' ) + cy.get( 'div' + helpers.sidebarClass() ) .contains( /Additional CSS/i ) .next( 'input' ) .then( ( $inputElem ) => { @@ -56,7 +56,7 @@ describe( 'Test CoBlocks Service Block', function() { } } ); - cy.get( 'div.edit-post-sidebar' ) + cy.get( 'div' + helpers.sidebarClass() ) .contains( /Additional CSS/i ) .next( 'input' ) .then( ( $inputElem ) => { diff --git a/src/blocks/shape-divider/test/shape-divider.cypress.js b/src/blocks/shape-divider/test/shape-divider.cypress.js index 33f15468f2c..ea84133e752 100644 --- a/src/blocks/shape-divider/test/shape-divider.cypress.js +++ b/src/blocks/shape-divider/test/shape-divider.cypress.js @@ -60,7 +60,7 @@ describe( 'Test CoBlocks Shape Divider Block', function() { helpers.openSettingsPanel( 'Divider settings' ); - cy.get( '.edit-post-sidebar' ) + cy.get( helpers.sidebarClass() ) .contains( 'Shape height' ).not( '.block-editor-block-card__description' ) .then( ( $settingSection ) => { cy.get( Cypress.$( $settingSection ).parent().parent() ) @@ -69,7 +69,7 @@ describe( 'Test CoBlocks Shape Divider Block', function() { .type( `{selectall}${ shapeHeight }` ); } ); - cy.get( '.edit-post-sidebar' ) + cy.get( helpers.sidebarClass() ) .contains( 'Background height' ).not( '.block-editor-block-card__description' ) .then( ( $settingSection ) => { cy.get( Cypress.$( $settingSection ).parent().parent() ) diff --git a/yarn.lock b/yarn.lock index 678525c1eca..de8e133b53b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4172,6 +4172,13 @@ dependencies: "@babel/runtime" "^7.16.0" +"@wordpress/escape-html@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@wordpress/escape-html/-/escape-html-3.4.0.tgz#ec625d409b018ff68d6081c66586fd420f74e122" + integrity sha512-KcUv+s0J/LEZEEvd+E3IkNCeW8wde0TjO+1HrcfvqI8Rfuc0zOAZeS/6ZqIeX0m/mhQ0xS2Y3e8hsnU+wAG6Mw== + dependencies: + "@babel/runtime" "^7.16.0" + "@wordpress/eslint-plugin@^12.7.0": version "12.9.0" resolved "https://registry.yarnpkg.com/@wordpress/eslint-plugin/-/eslint-plugin-12.9.0.tgz#c49f0a523c8c72ade28c2b86a975668832b22938"