diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index 414b2b1..f414c65 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -70,10 +70,25 @@ jobs: version: 'WordPress/WordPress#master', number: 'trunk', } + - { + name: 'WP 7.0', + version: 'WordPress/WordPress#7.0-branch', + number: '7.0', + } + - { + name: 'WP 6.9', + version: 'WordPress/WordPress#6.9-branch', + number: '6.9', + } + - { + name: 'WP 6.8', + version: 'WordPress/WordPress#6.8-branch', + number: '6.8', + } - { name: 'WP 6.7', version: 'WordPress/WordPress#6.7-branch', - number: '6.7' + number: '6.7', } - { name: 'WP 6.6', diff --git a/.gitignore b/.gitignore index 8d26efa..d11a9d2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ tests/cypress/screenshots tests/cypress/videos tests/cypress/reports +tests/cypress/downloads # wp-env files .wp-env.override.json diff --git a/run-all-cores.sh b/run-all-cores.sh index 41e9eed..50b3c4b 100755 --- a/run-all-cores.sh +++ b/run-all-cores.sh @@ -1,16 +1,14 @@ #!/bin/bash -MAJOR_VERSIONS="5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7" -TRUNK="master:trunk" +MAJOR_VERSIONS="5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0" +TRUNK="trunk" +TRUNK_UPDATE_VERSION="nightly" -VERSIONS="" -for MAJOR_VERSION in $MAJOR_VERSIONS; do - # This ensures the latest patch version is used. - VERSIONS="$VERSIONS $MAJOR_VERSION-branch:$MAJOR_VERSION" -done -VERSIONS="$TRUNK $VERSIONS" +VERSIONS="$MAJOR_VERSIONS $TRUNK" +FIRST_VERSION=$(echo "$MAJOR_VERSIONS" | cut -d " " -f 1) echo "Running tests for the following core versions: $VERSIONS" +echo "Starting once at core version: $FIRST_VERSION" SPEC="-- --quiet" @@ -21,17 +19,51 @@ do esac done -for VERSION in $VERSIONS; do - CORE=$(echo $VERSION|cut -d ":" -f 1) - NUMBER=$(echo $VERSION|cut -d ":" -f 2) - [[ -z "$NUMBER" ]] && NUMBER="$CORE" +cleanup() { + npm run env:stop > /dev/null || true +} + +trap cleanup EXIT + +run_cypress_for_version() { + EXPECTED_VERSION="$1" + ACTUAL_VERSION=$(npm run env run tests-cli -- wp core version | grep -E '^[0-9]+(\.[0-9]+)*([.-][A-Za-z0-9]+)*$' | tail -n 1 | tr -d '\r') echo "**********************************************" - echo "Core: $CORE, Version number: $NUMBER" + echo "Expected version number: $EXPECTED_VERSION" + echo "Detected version number: $ACTUAL_VERSION" echo "**********************************************" - ./tests/bin/set-core-version.js $CORE - npm run env:start > /dev/null - npm run env run tests-cli "core update-db" > /dev/null + if [[ -z "$ACTUAL_VERSION" ]]; then + echo "Unable to determine installed WordPress version." + return 1 + fi + if [[ "$EXPECTED_VERSION" != "$TRUNK" && ! "$ACTUAL_VERSION" =~ ^${EXPECTED_VERSION//./\.}(\.[0-9]+)*$ ]]; then + echo "WordPress version mismatch: expected $EXPECTED_VERSION or a patch release based on it, detected $ACTUAL_VERSION" + return 1 + fi + npm run env run tests-cli -- wp theme activate twentytwentyone > /dev/null || true + npm run env run tests-cli -- wp core update-db > /dev/null || true npm run env clean > /dev/null - CYPRESS_WORDPRESS_CORE="$NUMBER" npm run cypress:run $SPEC - npm run env:stop > /dev/null + CYPRESS_WORDPRESS_CORE="$EXPECTED_VERSION" npm run cypress:run $SPEC +} + +./tests/bin/set-core-version.js "$FIRST_VERSION-branch" +if ! npm run env:start > /dev/null; then + echo "Initial wp-env start failed; retrying once." + npm run env:start > /dev/null +fi +run_cypress_for_version "$FIRST_VERSION" + +for MAJOR_VERSION in $MAJOR_VERSIONS; do + if [[ "$MAJOR_VERSION" == "$FIRST_VERSION" ]]; then + continue + fi + + echo "Updating WordPress core to $MAJOR_VERSION" + npm run env run tests-cli -- wp core update -- --version=$MAJOR_VERSION --force > /dev/null + npm run env run tests-cli -- wp core update --minor > /dev/null + run_cypress_for_version "$MAJOR_VERSION" done + +echo "Updating WordPress core to trunk ($TRUNK_UPDATE_VERSION)" +npm run env run tests-cli -- wp core update -- --version=$TRUNK_UPDATE_VERSION --force > /dev/null +run_cypress_for_version "$TRUNK" diff --git a/src/commands/insert-block.ts b/src/commands/insert-block.ts index 6ad7c8f..a3cb732 100644 --- a/src/commands/insert-block.ts +++ b/src/commands/insert-block.ts @@ -15,47 +15,69 @@ import { getIframe } from '../functions/get-iframe'; * }); * ``` */ -export const insertBlock = (type: string, name?: string): void => { +export const insertBlock = ( + type: string, + name?: string +): Cypress.Chainable => { const [namespace = '', ...blockNameRest] = type.split('/'); let blockNames = [ blockNameRest.join('/').replace(/\//g, '-'), blockNameRest.join('/').replace(/\//g, String.raw`\/`), ]; - blockNames = blockNames.filter((x, i, a) => a.indexOf(x) == i); - // let blockName = blockNameRest.join('/').replace( '/', '\\/' ); + blockNames = blockNames.filter((x, i, a) => a.indexOf(x) === i); - let inserterBtn: Cypress.Chainable>; - let search = ''; + let inserterBtnSelector = ''; + let insertedBlockId = ''; - if (typeof name === 'string' && name.length) { - search = name; - } else { - search = type; - } + const search = + typeof name === 'string' && name.length + ? name + : typeof type === 'string' + ? type + : ''; - // Start of block inserter toggle button click logic. - cy.get('body').then($body => { - const selectors = [ - 'button[aria-label="Add block"]', // 5.7 - 'button[aria-label="Toggle block inserter"]', // 6.4 - 'button[aria-label="Block Inserter"]', // 6.8 - ]; + const inserterSelectors = [ + 'button[aria-label="Add block"]', // 5.7 + 'button[aria-label="Toggle block inserter"]', // 6.4 + 'button[aria-label="Block Inserter"]', // 6.8 + ]; + const searchInputSelector = + 'input[placeholder="Search"], input[aria-label="Search"], input[aria-label="Search for blocks and patterns"]'; + + const resolveBlockId = ( + $block: JQuery, + blockType: string + ): string => { + const existingId = String($block.prop('id') || $block.attr('id') || ''); + if (existingId.length) { + return existingId; + } - selectors.forEach(selector => { + const dataBlock = String($block.attr('data-block') || ''); + const generatedId = dataBlock.length + ? `block-${dataBlock}` + : `cypress-${blockType.replace(/\//g, '-')}-${Date.now()}-${Math.floor( + Math.random() * 10000 + )}`; + $block.attr('id', generatedId); + + return generatedId; + }; + + cy.get('body').then($body => { + inserterSelectors.forEach(selector => { if ($body.find(selector).length) { cy.get(selector).then($button => { if ($button.length) { - inserterBtn = cy.wrap($button); - inserterBtn.first().click(); + inserterBtnSelector = selector; + cy.get(selector).first().click(); } }); } }); }); - // End of block inserter toggle button click logic. - // Start of Block tab click logic. cy.get('button[role="tab"]') .contains('Blocks') .then($tab => { @@ -63,15 +85,13 @@ export const insertBlock = (type: string, name?: string): void => { cy.wrap($tab).click(); } }); - // End of Block tab click logic. - // Start of Block search logic. - cy.get('input[placeholder="Search"]').then($input => { - if ($input.length) { - cy.wrap($input).type(search); + cy.get('body').then($body => { + if ($body.find(searchInputSelector).length) { + cy.get(searchInputSelector).first().clear(); + cy.get(searchInputSelector).first().type(search); } }); - // End of Block search logic. blockNames.forEach(blockName => { const blockSelector = `.editor-block-list-item-${ @@ -79,44 +99,54 @@ export const insertBlock = (type: string, name?: string): void => { }${blockName}`; cy.get('body').then($body => { - if ($body.find(blockSelector).length) { - // Start of Block insertion by click logic. - cy.get(blockSelector).then($block => { + const modernInserterSelector = `.block-editor-inserter__menu [data-type="${type}"], .block-editor-inserter__results [data-type="${type}"]`; + const selectorToUse = $body.find(blockSelector).length + ? blockSelector + : $body.find(modernInserterSelector).length + ? modernInserterSelector + : ''; + + if (selectorToUse.length) { + cy.get(selectorToUse).then($block => { if ($block.length) { - cy.wrap($block).click(); - inserterBtn.click(); + cy.wrap($block).first().click(); + if (inserterBtnSelector.length) { + cy.get(inserterBtnSelector).first().click(); + } - const [ns, rest] = type.split('/'); // namespace = ns, second namespace or block name = rest + const [ns, rest] = type.split('/'); + const blockType = `${ns}/${rest}`; + const blockSelectorByType = `.wp-block[data-type="${blockType}"]`; - cy.get('body').then($body => { - if ($body.find('iframe[name="editor-canvas"]').length) { - // Works with WP 6.4 + cy.get('body').then($editorBody => { + if ($editorBody.find('iframe[name="editor-canvas"]').length) { getIframe('iframe[name="editor-canvas"]').then($iframe => { - const blockInIframe = $iframe.find( - `.wp-block[data-type="${ns}/${rest}"]` - ); + const blockInIframe = $iframe.find(blockSelectorByType); if (blockInIframe.length > 0) { - cy.wrap(blockInIframe.last().prop('id')); + insertedBlockId = resolveBlockId( + blockInIframe.last(), + blockType + ); + cy.wrap(insertedBlockId); } }); - } else if ( - $body.find(`.wp-block[data-type="${ns}/${rest}"]`).length - ) { - // Works with WP 5.7 - cy.get(`.wp-block[data-type="${ns}/${rest}"]`).then( - $blockInEditor => { - expect($blockInEditor.length).to.equal(1); - cy.wrap($blockInEditor.prop('id')); - } - ); + } else if ($editorBody.find(blockSelectorByType).length) { + cy.get(blockSelectorByType).then($blockInEditor => { + insertedBlockId = resolveBlockId( + $blockInEditor.last(), + blockType + ); + cy.wrap(insertedBlockId); + }); } else { - throw new Error(`${ns}/${rest} not found.`); + throw new Error(`${blockType} not found.`); } }); } }); - // End of Block insertion by click logic. } }); }); + + return cy.wrap(null).then(() => insertedBlockId); }; diff --git a/src/index.ts b/src/index.ts index d8fbbef..0152714 100644 --- a/src/index.ts +++ b/src/index.ts @@ -65,6 +65,17 @@ declare global { } } +// Ignore promises rejected due to missed transitions. +// These are common on CI environments due to the speed of the tests and the environment. +Cypress.on('uncaught:exception', err => { + if ( + err?.name === 'AbortError' && + err?.message?.includes('Transition was skipped') + ) { + return false; + } +}); + // Register commands Cypress.Commands.add('checkPostExists', checkPostExists); Cypress.Commands.add('classicCreatePost', classicCreatePost); diff --git a/tests/cypress/e2e/insert-block.test.js b/tests/cypress/e2e/insert-block.test.js index 6cf7c87..e219506 100644 --- a/tests/cypress/e2e/insert-block.test.js +++ b/tests/cypress/e2e/insert-block.test.js @@ -88,10 +88,11 @@ describe('Command: insertBlock', () => { }); it('Should be able to insert custom block', () => { - if ( - 'trunk' !== Cypress.env('WORDPRESS_CORE').toString() && - compare(Cypress.env('WORDPRESS_CORE').toString(), '6.1', '<') - ) { + const wordpressCore = Cypress.env('WORDPRESS_CORE') + ? Cypress.env('WORDPRESS_CORE').toString() + : 'trunk'; + + if ('trunk' !== wordpressCore && compare(wordpressCore, '6.1', '<')) { // WinAmp block does not support this version of WordPress. assert(true, 'Skipping test, WinAmp block does not exist'); return;