diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index 5451798fb3bad7..8cacc99882fa8a 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Added `createReusableBlock` function to make it easier to create a simple reusable block ([#37333](https://github.com/WordPress/gutenberg/pull/37333)). + ### New Features - Added `getOption` and `setOption` functions to make it easier to set and reset options such as the site title and site tagline ([#37139](https://github.com/WordPress/gutenberg/pull/37139)). diff --git a/packages/e2e-test-utils/README.md b/packages/e2e-test-utils/README.md index 210c15c101433c..5512371467a653 100644 --- a/packages/e2e-test-utils/README.md +++ b/packages/e2e-test-utils/README.md @@ -161,6 +161,15 @@ _Parameters_ - _object.excerpt_ `[string]`: Excerpt of the new post. - _object.showWelcomeGuide_ `[boolean]`: Whether to show the welcome guide. +### createReusableBlock + +Creates a simple reusable block with a paragraph block. + +_Parameters_ + +- _content_ `string`: Paragraph block's content +- _title_ `title`: Reusable block's name. + ### createURL Creates new URL by parsing base URL, WPPath and query string. diff --git a/packages/e2e-test-utils/src/create-reusable-block.js b/packages/e2e-test-utils/src/create-reusable-block.js new file mode 100644 index 00000000000000..74276d2be64317 --- /dev/null +++ b/packages/e2e-test-utils/src/create-reusable-block.js @@ -0,0 +1,40 @@ +/** + * Internal dependencies + */ +import { insertBlock } from './inserter'; +import { clickMenuItem } from './click-menu-item'; +import { clickBlockToolbarButton } from './click-block-toolbar-button'; + +/** + * Creates a simple reusable block with a paragraph block. + * + * @param {string} content Paragraph block's content + * @param {title} title Reusable block's name. + */ +export const createReusableBlock = async ( content, title ) => { + const reusableBlockNameInputSelector = + '.reusable-blocks-menu-items__convert-modal .components-text-control__input'; + // Insert a paragraph block + await insertBlock( 'Paragraph' ); + await page.keyboard.type( content ); + + await clickBlockToolbarButton( 'Options' ); + await clickMenuItem( 'Add to Reusable blocks' ); + const nameInput = await page.waitForSelector( + reusableBlockNameInputSelector + ); + await nameInput.click(); + await page.keyboard.type( title ); + await page.keyboard.press( 'Enter' ); + + // Wait for creation to finish + await page.waitForXPath( + '//*[contains(@class, "components-snackbar")]/*[text()="Reusable block created."]' + ); + + // Check that we have a reusable block on the page + const block = await page.waitForSelector( + '.block-editor-block-list__block[data-type="core/block"]' + ); + expect( block ).not.toBeNull(); +}; diff --git a/packages/e2e-test-utils/src/index.js b/packages/e2e-test-utils/src/index.js index f138d7a121faef..94e97f95d11e15 100644 --- a/packages/e2e-test-utils/src/index.js +++ b/packages/e2e-test-utils/src/index.js @@ -15,6 +15,7 @@ export { clickMenuItem } from './click-menu-item'; export { clickOnCloseModalButton } from './click-on-close-modal-button'; export { clickOnMoreMenuItem } from './click-on-more-menu-item'; export { createNewPost } from './create-new-post'; +export { createReusableBlock } from './create-reusable-block'; export { createUser } from './create-user'; export { createURL } from './create-url'; export { deactivatePlugin } from './deactivate-plugin'; diff --git a/packages/e2e-tests/specs/editor/various/block-grouping.test.js b/packages/e2e-tests/specs/editor/various/block-grouping.test.js index ba482cdbbee462..a07e7967988f23 100644 --- a/packages/e2e-tests/specs/editor/various/block-grouping.test.js +++ b/packages/e2e-tests/specs/editor/various/block-grouping.test.js @@ -13,6 +13,7 @@ import { getAvailableBlockTransforms, activatePlugin, deactivatePlugin, + createReusableBlock, } from '@wordpress/e2e-test-utils'; async function insertBlocksOfSameType() { @@ -122,24 +123,7 @@ describe( 'Block Grouping', () => { }; const paragraphText = 'hi'; - const reusableBlockNameInputSelector = - '.reusable-blocks-menu-items__convert-modal .components-text-control__input'; - await insertBlock( 'Paragraph' ); - await page.keyboard.type( paragraphText ); - - await clickBlockToolbarButton( 'Options' ); - await clickMenuItem( 'Add to Reusable blocks' ); - const nameInput = await page.waitForSelector( - reusableBlockNameInputSelector - ); - await nameInput.click(); - await page.keyboard.type( 'Block' ); - await page.keyboard.press( 'Enter' ); - - // Wait for creation to finish - await page.waitForXPath( - '//*[contains(@class, "components-snackbar")]/*[text()="Reusable block created."]' - ); + await createReusableBlock( paragraphText, 'Block' ); // Group await clickBlockToolbarButton( 'Options' ); await clickMenuItem( 'Group' ); diff --git a/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js b/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js index 953bf3e11eaa6a..0cf2ed53210993 100644 --- a/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js +++ b/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js @@ -14,6 +14,7 @@ import { toggleGlobalBlockInserter, openDocumentSettingsSidebar, saveDraft, + createReusableBlock, } from '@wordpress/e2e-test-utils'; const reusableBlockNameInputSelector = @@ -44,32 +45,6 @@ const clearAllBlocks = async () => { } ); }; -const createReusableBlock = async ( content, title ) => { - // Insert a paragraph block - await insertBlock( 'Paragraph' ); - await page.keyboard.type( content ); - - await clickBlockToolbarButton( 'Options' ); - await clickMenuItem( 'Add to Reusable blocks' ); - const nameInput = await page.waitForSelector( - reusableBlockNameInputSelector - ); - await nameInput.click(); - await page.keyboard.type( title ); - await page.keyboard.press( 'Enter' ); - - // Wait for creation to finish - await page.waitForXPath( - '//*[contains(@class, "components-snackbar")]/*[text()="Reusable block created."]' - ); - - // Check that we have a reusable block on the page - const block = await page.waitForSelector( - '.block-editor-block-list__block[data-type="core/block"]' - ); - expect( block ).not.toBeNull(); -}; - describe( 'Reusable blocks', () => { afterAll( async () => { await trashAllPosts( 'wp_block' ); diff --git a/packages/e2e-tests/specs/site-editor/multi-entity-saving.test.js b/packages/e2e-tests/specs/site-editor/multi-entity-saving.test.js index 0f965a15dbff48..65975e832aa016 100644 --- a/packages/e2e-tests/specs/site-editor/multi-entity-saving.test.js +++ b/packages/e2e-tests/specs/site-editor/multi-entity-saving.test.js @@ -11,6 +11,7 @@ import { trashAllPosts, activateTheme, clickButton, + createReusableBlock, } from '@wordpress/e2e-test-utils'; /** @@ -23,13 +24,9 @@ describe( 'Multi-entity save flow', () => { const checkedBoxSelector = '.components-checkbox-control__checked'; const checkboxInputSelector = '.components-checkbox-control__input'; const entitiesSaveSelector = '.editor-entities-saved-states__save-button'; - const templatePartSelector = '*[data-type="core/template-part"]'; - const activatedTemplatePartSelector = `${ templatePartSelector }.block-editor-block-list__layout`; const savePanelSelector = '.entities-saved-states__panel'; const closePanelButtonSelector = '.editor-post-publish-panel__header-cancel-button button:not(:disabled)'; - const createNewButtonSelector = - '//button[contains(text(), "New template part")]'; // Reusable assertions across Post/Site editors. const assertAllBoxesChecked = async () => { @@ -52,6 +49,7 @@ describe( 'Multi-entity save flow', () => { await activateTheme( 'tt1-blocks' ); await trashAllPosts( 'wp_template' ); await trashAllPosts( 'wp_template_part' ); + await trashAllPosts( 'wp_block' ); // Get the current Site Title and Site Tagline, so that we can reset // them back to the original values once the test suite has finished. @@ -79,8 +77,6 @@ describe( 'Multi-entity save flow', () => { const saveA11ySelector = '.edit-post-layout__toggle-entities-saved-states-panel-button'; const publishPanelSelector = '.editor-post-publish-panel'; - const confirmTitleButtonSelector = - '.wp-block-template-part__placeholder-create-new__title-form .components-button.is-primary'; // Reusable assertions inside Post editor. const assertMultiSaveEnabled = async () => { @@ -97,9 +93,10 @@ describe( 'Multi-entity save flow', () => { expect( multiSaveButton ).toBeNull(); }; - // Template parts can't be used in posts, so this test needs to be rebuilt using perhaps reusable blocks. - it.skip( 'Save flow should work as expected.', async () => { + it( 'Save flow should work as expected.', async () => { + await createNewPost(); // Edit the page some. + await page.waitForSelector( '.editor-post-title' ); await page.click( '.editor-post-title' ); await page.keyboard.type( 'Test Post...' ); await page.keyboard.press( 'Enter' ); @@ -113,21 +110,11 @@ describe( 'Multi-entity save flow', () => { await assertExistance( publishPanelSelector, false ); await assertExistance( savePanelSelector, false ); - // Add a template part and edit it. - await insertBlock( 'Template Part' ); - const createNewButton = await page.waitForXPath( - createNewButtonSelector - ); - await createNewButton.click(); - const confirmTitleButton = await page.waitForSelector( - confirmTitleButtonSelector - ); - await confirmTitleButton.click(); - - await page.waitForSelector( activatedTemplatePartSelector ); - await page.click( '.block-editor-button-block-appender' ); - await page.click( '.editor-block-list-item-paragraph' ); - await page.keyboard.type( 'some words...' ); + // Add a reusable block and edit it. + await createReusableBlock( 'Hi!', 'Test' ); + await page.waitForSelector( 'p[data-type="core/paragraph"]' ); + await page.click( 'p[data-type="core/paragraph"]' ); + await page.keyboard.type( 'Oh!' ); // Should trigger multi-entity save button once template part edited. await assertMultiSaveEnabled(); @@ -191,13 +178,11 @@ describe( 'Multi-entity save flow', () => { await assertMultiSaveDisabled(); await assertExistance( saveA11ySelector, false ); - // Update template part. - await page.click( templatePartSelector ); - await page.click( - `${ templatePartSelector } .wp-block[data-type="core/paragraph"]` - ); - await page.keyboard.type( '...some more words...' ); - await page.keyboard.press( 'Enter' ); + // Update reusable block again. + await page.click( 'p[data-type="core/paragraph"]' ); + // We need to click again due to the clickthrough overlays in reusable blocks. + await page.click( 'p[data-type="core/paragraph"]' ); + await page.keyboard.type( 'R!' ); // Multi-entity saving should be enabled. await assertMultiSaveEnabled(); diff --git a/packages/e2e-tests/specs/site-editor/template-part.test.js b/packages/e2e-tests/specs/site-editor/template-part.test.js index 294b361b63cc84..cd98b24947ed3f 100644 --- a/packages/e2e-tests/specs/site-editor/template-part.test.js +++ b/packages/e2e-tests/specs/site-editor/template-part.test.js @@ -2,9 +2,7 @@ * WordPress dependencies */ import { - createNewPost, insertBlock, - disablePrePublishChecks, trashAllPosts, activateTheme, getAllBlocks, @@ -260,73 +258,94 @@ describe( 'Template Part', () => { finalTemplateParts.length - initialTemplateParts.length ).toBe( 1 ); } ); - } ); - - describe( 'Template part placeholder', () => { - // Test constants for template part. - const testContent = 'some words...'; - - // Selectors - const entitiesSaveSelector = - '.editor-entities-saved-states__save-button'; - const savePostSelector = '.editor-post-publish-button__button'; - const templatePartSelector = '*[data-type="core/template-part"]'; - const activatedTemplatePartSelector = `${ templatePartSelector }.block-editor-block-list__layout`; - const testContentSelector = `//p[contains(., "${ testContent }")]`; - const createNewButtonSelector = - '//button[contains(text(), "New template part")]'; - const chooseExistingButtonSelector = - '//button[contains(text(), "Choose existing")]'; - const confirmTitleButtonSelector = - '.wp-block-template-part__placeholder-create-new__title-form .components-button.is-primary'; - - // Template parts can't be used in posts, so this test needs to be rebuilt for the template editor. - it.skip( 'Should insert new template part on creation', async () => { - await createNewPost(); - await disablePrePublishChecks(); - // Create new template part. - await insertBlock( 'Template Part' ); - await page.waitForXPath( chooseExistingButtonSelector ); - const [ createNewButton ] = await page.$x( - createNewButtonSelector - ); - await createNewButton.click(); - const confirmTitleButton = await page.waitForSelector( - confirmTitleButtonSelector - ); - await page.keyboard.press( 'Tab' ); - await page.keyboard.press( 'Tab' ); - await page.keyboard.type( 'Create New' ); - await confirmTitleButton.click(); - - const newTemplatePart = await page.waitForSelector( - activatedTemplatePartSelector - ); - expect( newTemplatePart ).toBeTruthy(); - - // Finish creating template part, insert some text, and save. - await page.click( '.block-editor-button-block-appender' ); - await page.click( '.editor-block-list-item-paragraph' ); - await page.keyboard.type( testContent ); - await page.click( savePostSelector ); - await page.click( entitiesSaveSelector ); - - await createNewPost(); - // Try to insert the template part we created. - await insertBlock( 'Template Part' ); - const chooseExistingButton = await page.waitForXPath( - chooseExistingButtonSelector - ); - await chooseExistingButton.click(); - const preview = await page.waitForSelector( - '[aria-label="Create New"]' - ); - await preview.click(); - await page.waitForSelector( activatedTemplatePartSelector ); - const templatePartContent = await page.waitForXPath( - testContentSelector - ); - expect( templatePartContent ).toBeTruthy(); + describe( 'Template part placeholder', () => { + // Test constants for template part. + const testContent = 'some words...'; + + // Selectors + const entitiesSaveSelector = + '.editor-entities-saved-states__save-button'; + const savePostSelector = '.edit-site-save-button__button'; + const templatePartSelector = '*[data-type="core/template-part"]'; + const activatedTemplatePartSelector = `${ templatePartSelector }.block-editor-block-list__layout`; + const createNewButtonSelector = + '//button[contains(text(), "New template part")]'; + const chooseExistingButtonSelector = + '//button[contains(text(), "Choose existing")]'; + const confirmTitleButtonSelector = + '.wp-block-template-part__placeholder-create-new__title-form .components-button.is-primary'; + + it( 'Should insert new template part on creation', async () => { + let siteEditorCanvas = canvas(); + await awaitHeaderAndFooterLoad(); + + // Create new template part. + await insertBlock( 'Template Part' ); + await siteEditorCanvas.waitForXPath( + chooseExistingButtonSelector + ); + const [ createNewButton ] = await siteEditorCanvas.$x( + createNewButtonSelector + ); + await createNewButton.click(); + const confirmTitleButton = await page.waitForSelector( + confirmTitleButtonSelector + ); + await page.keyboard.press( 'Tab' ); + await page.keyboard.press( 'Tab' ); + await page.keyboard.type( 'Create New' ); + await confirmTitleButton.click(); + + const newTemplatePart = await siteEditorCanvas.waitForSelector( + activatedTemplatePartSelector + ); + expect( newTemplatePart ).toBeTruthy(); + + // Finish creating template part, insert some text, and save. + await siteEditorCanvas.waitForSelector( + '.block-editor-button-block-appender' + ); + await siteEditorCanvas.click( + '.block-editor-button-block-appender' + ); + await page.waitForSelector( + '.editor-block-list-item-paragraph' + ); + await page.click( '.editor-block-list-item-paragraph' ); + await page.keyboard.type( testContent ); + await page.click( savePostSelector ); + await page.click( entitiesSaveSelector ); + + // Reload the page so as the new template part is available in the existing template parts. + await siteEditor.visit(); + siteEditorCanvas = canvas(); + await awaitHeaderAndFooterLoad(); + // Try to insert the template part we created. + await insertBlock( 'Template Part' ); + const chooseExistingButton = await siteEditorCanvas.waitForXPath( + chooseExistingButtonSelector + ); + await chooseExistingButton.click(); + await page.waitForSelector( + '.wp-block-template-part__selection-preview-container' + ); + const preview = await page.waitForSelector( + '.wp-block-template-part__selection-preview-item[aria-label="Create New"]' + ); + await preview.click(); + // We now have the same template part two times in the page, so check accordingly. + const paragraphs = await siteEditorCanvas.$$eval( + '[data-type="core/template-part"] > p:first-child', + ( options ) => + options.map( ( option ) => option.textContent ) + ); + expect( paragraphs ).toHaveLength( 2 ); + expect( + paragraphs.every( + ( paragraph ) => paragraph === testContent + ) + ).toBeTruthy(); + } ); } ); } ); } );