diff --git a/packages/e2e-test-utils/README.md b/packages/e2e-test-utils/README.md index e987e7002839b..039bd766b1963 100644 --- a/packages/e2e-test-utils/README.md +++ b/packages/e2e-test-utils/README.md @@ -88,7 +88,7 @@ Clicks on More Menu item, searches for the button with the text provided and cli ### createEmbeddingMatcher -[src/index.js#L48-L48](src/index.js#L48-L48) +[src/index.js#L51-L51](src/index.js#L51-L51) Creates a function to determine if a request is embedding a certain URL. @@ -102,7 +102,7 @@ Creates a function to determine if a request is embedding a certain URL. ### createJSONResponse -[src/index.js#L48-L48](src/index.js#L48-L48) +[src/index.js#L51-L51](src/index.js#L51-L51) Respond to a request with a JSON response. @@ -141,7 +141,7 @@ Creates new URL by parsing base URL, WPPath and query string. ### createURLMatcher -[src/index.js#L48-L48](src/index.js#L48-L48) +[src/index.js#L51-L51](src/index.js#L51-L51) Creates a function to determine if a request is calling a URL with the substring present. @@ -220,10 +220,20 @@ Finds the button responsible for toggling the sidebar panel with the provided ti `?ElementHandle`: Object that represents an in-page DOM element. -### getAllBlocks +### getAllBlockInserterItemTitles [src/index.js#L18-L18](src/index.js#L18-L18) +Returns an array of strings with all inserter item titles. + +**Returns** + +`Promise`: Promise resolving with an array containing all inserter item titles. + +### getAllBlocks + +[src/index.js#L19-L19](src/index.js#L19-L19) + Returns an array with all blocks; Equivalent to calling wp.data.select( 'core/editor' ).getBlocks(); **Returns** @@ -232,7 +242,7 @@ Returns an array with all blocks; Equivalent to calling wp.data.select( 'core/ed ### getAvailableBlockTransforms -[src/index.js#L19-L19](src/index.js#L19-L19) +[src/index.js#L20-L20](src/index.js#L20-L20) Returns an array of strings with all block titles, that the current selected block can be transformed into. @@ -243,7 +253,7 @@ that the current selected block can be transformed into. ### getEditedPostContent -[src/index.js#L20-L20](src/index.js#L20-L20) +[src/index.js#L21-L21](src/index.js#L21-L21) Returns a promise which resolves with the edited post content (HTML string). @@ -253,7 +263,7 @@ Returns a promise which resolves with the edited post content (HTML string). ### hasBlockSwitcher -[src/index.js#L21-L21](src/index.js#L21-L21) +[src/index.js#L22-L22](src/index.js#L22-L22) Returns a boolean indicating if the current selected block has a block switcher or not. @@ -263,7 +273,7 @@ Returns a boolean indicating if the current selected block has a block switcher ### insertBlock -[src/index.js#L22-L22](src/index.js#L22-L22) +[src/index.js#L23-L23](src/index.js#L23-L23) Opens the inserter, searches for the given term, then selects the first result that appears. @@ -275,7 +285,7 @@ result that appears. ### installPlugin -[src/index.js#L23-L23](src/index.js#L23-L23) +[src/index.js#L24-L24](src/index.js#L24-L24) Installs a plugin from the WP.org repository. @@ -286,7 +296,7 @@ Installs a plugin from the WP.org repository. ### isCurrentURL -[src/index.js#L24-L24](src/index.js#L24-L24) +[src/index.js#L25-L25](src/index.js#L25-L25) Checks if current URL is a WordPress path. @@ -301,7 +311,7 @@ Checks if current URL is a WordPress path. ### isInDefaultBlock -[src/index.js#L25-L25](src/index.js#L25-L25) +[src/index.js#L26-L26](src/index.js#L26-L26) Checks if the block that is focused is the default block. @@ -311,7 +321,7 @@ Checks if the block that is focused is the default block. ### loginUser -[src/index.js#L26-L26](src/index.js#L26-L26) +[src/index.js#L27-L27](src/index.js#L27-L27) Performs log in with specified username and password. @@ -322,7 +332,7 @@ Performs log in with specified username and password. ### mockOrTransform -[src/index.js#L48-L48](src/index.js#L48-L48) +[src/index.js#L51-L51](src/index.js#L51-L51) Mocks a request with the supplied mock object, or allows it to run with an optional transform, based on the deserialised JSON response for the request. @@ -339,26 +349,38 @@ deserialised JSON response for the request. ### observeFocusLoss -[src/index.js#L27-L27](src/index.js#L27-L27) +[src/index.js#L28-L28](src/index.js#L28-L28) Binds to the document on page load which throws an error if a `focusout` event occurs without a related target (i.e. focus loss). +### openAllBlockInserterCategories + +[src/index.js#L29-L29](src/index.js#L29-L29) + +Opens all block inserter categories. + ### openDocumentSettingsSidebar -[src/index.js#L28-L28](src/index.js#L28-L28) +[src/index.js#L30-L30](src/index.js#L30-L30) Clicks on the button in the header which opens Document Settings sidebar when it is closed. +### openGlobalBlockInserter + +[src/index.js#L31-L31](src/index.js#L31-L31) + +Opens the global block inserter. + ### openPublishPanel -[src/index.js#L29-L29](src/index.js#L29-L29) +[src/index.js#L32-L32](src/index.js#L32-L32) Opens the publish panel. ### pressKeyTimes -[src/index.js#L30-L30](src/index.js#L30-L30) +[src/index.js#L33-L33](src/index.js#L33-L33) Presses the given keyboard key a number of times in sequence. @@ -373,7 +395,7 @@ Presses the given keyboard key a number of times in sequence. ### pressKeyWithModifier -[src/index.js#L31-L31](src/index.js#L31-L31) +[src/index.js#L34-L34](src/index.js#L34-L34) Performs a key press with modifier (Shift, Control, Meta, Alt), where each modifier is normalized to platform-specific modifier. @@ -385,7 +407,7 @@ is normalized to platform-specific modifier. ### publishPost -[src/index.js#L32-L32](src/index.js#L32-L32) +[src/index.js#L35-L35](src/index.js#L35-L35) Publishes the post, resolving once the request is complete (once a notice is displayed). @@ -396,7 +418,7 @@ is displayed). ### publishPostWithPrePublishChecksDisabled -[src/index.js#L33-L33](src/index.js#L33-L33) +[src/index.js#L36-L36](src/index.js#L36-L36) Publishes the post without the pre-publish checks, resolving once the request is complete (once a notice is displayed). @@ -407,7 +429,7 @@ resolving once the request is complete (once a notice is displayed). ### saveDraft -[src/index.js#L34-L34](src/index.js#L34-L34) +[src/index.js#L37-L37](src/index.js#L37-L37) Saves the post as a draft, resolving once the request is complete (once the "Saved" indicator is displayed). @@ -418,7 +440,7 @@ Saves the post as a draft, resolving once the request is complete (once the ### searchForBlock -[src/index.js#L35-L35](src/index.js#L35-L35) +[src/index.js#L38-L38](src/index.js#L38-L38) Search for block in the global inserter @@ -428,7 +450,7 @@ Search for block in the global inserter ### selectBlockByClientId -[src/index.js#L36-L36](src/index.js#L36-L36) +[src/index.js#L39-L39](src/index.js#L39-L39) Given the clientId of a block, selects the block on the editor. @@ -438,7 +460,7 @@ Given the clientId of a block, selects the block on the editor. ### setBrowserViewport -[src/index.js#L37-L37](src/index.js#L37-L37) +[src/index.js#L40-L40](src/index.js#L40-L40) Sets browser viewport to specified type. @@ -448,7 +470,7 @@ Sets browser viewport to specified type. ### setPostContent -[src/index.js#L38-L38](src/index.js#L38-L38) +[src/index.js#L41-L41](src/index.js#L41-L41) Sets code editor content @@ -462,7 +484,7 @@ Sets code editor content ### setUpResponseMocking -[src/index.js#L48-L48](src/index.js#L48-L48) +[src/index.js#L51-L51](src/index.js#L51-L51) Sets up mock checks and responses. Accepts a list of mock settings with the following properties: @@ -493,7 +515,7 @@ If none of the mock settings match the request, the request is allowed to contin ### switchEditorModeTo -[src/index.js#L39-L39](src/index.js#L39-L39) +[src/index.js#L42-L42](src/index.js#L42-L42) Switches editor mode. @@ -503,21 +525,21 @@ Switches editor mode. ### switchUserToAdmin -[src/index.js#L40-L40](src/index.js#L40-L40) +[src/index.js#L43-L43](src/index.js#L43-L43) Switches the current user to the admin user (if the user running the test is not already the admin user). ### switchUserToTest -[src/index.js#L41-L41](src/index.js#L41-L41) +[src/index.js#L44-L44](src/index.js#L44-L44) Switches the current user to whichever user we should be running the tests as (if we're not already that user). ### toggleScreenOption -[src/index.js#L42-L42](src/index.js#L42-L42) +[src/index.js#L45-L45](src/index.js#L45-L45) Toggles the screen option with the given label. @@ -528,7 +550,7 @@ Toggles the screen option with the given label. ### transformBlockTo -[src/index.js#L43-L43](src/index.js#L43-L43) +[src/index.js#L46-L46](src/index.js#L46-L46) Converts editor's block type. @@ -538,7 +560,7 @@ Converts editor's block type. ### uninstallPlugin -[src/index.js#L44-L44](src/index.js#L44-L44) +[src/index.js#L47-L47](src/index.js#L47-L47) Uninstalls a plugin. @@ -548,7 +570,7 @@ Uninstalls a plugin. ### visitAdminPage -[src/index.js#L45-L45](src/index.js#L45-L45) +[src/index.js#L48-L48](src/index.js#L48-L48) Visits admin page; if user is not logged in then it logging in it first, then visits admin page. @@ -559,7 +581,7 @@ Visits admin page; if user is not logged in then it logging in it first, then vi ### waitForWindowDimensions -[src/index.js#L46-L46](src/index.js#L46-L46) +[src/index.js#L49-L49](src/index.js#L49-L49) Function that waits until the page viewport has the required dimensions. It is being used to address a problem where after using setViewport the execution may continue, diff --git a/packages/e2e-test-utils/src/get-all-block-inserter-item-titles.js b/packages/e2e-test-utils/src/get-all-block-inserter-item-titles.js new file mode 100644 index 0000000000000..859adc89bac15 --- /dev/null +++ b/packages/e2e-test-utils/src/get-all-block-inserter-item-titles.js @@ -0,0 +1,24 @@ +/** + * External dependencies + */ +import { sortBy, uniq } from 'lodash'; + +/** + * Returns an array of strings with all inserter item titles. + * + * @return {Promise} Promise resolving with an array containing all inserter item titles. + */ +export async function getAllBlockInserterItemTitles() { + const inserterItemTitles = await page.evaluate( () => { + return Array.from( + document.querySelectorAll( + '.editor-inserter__results .editor-block-types-list__item-title' + ) + ).map( + ( inserterItem ) => { + return inserterItem.innerText; + } + ); + } ); + return sortBy( uniq( inserterItemTitles ) ); +} diff --git a/packages/e2e-test-utils/src/index.js b/packages/e2e-test-utils/src/index.js index 09e11bf9ec0ed..3543abbbb3609 100644 --- a/packages/e2e-test-utils/src/index.js +++ b/packages/e2e-test-utils/src/index.js @@ -15,6 +15,7 @@ export { enablePrePublishChecks } from './enable-pre-publish-checks'; export { ensureSidebarOpened } from './ensure-sidebar-opened'; export { findSidebarPanelToggleButtonWithTitle } from './find-sidebar-panel-toggle-button-with-title'; export { findSidebarPanelWithTitle } from './find-sidebar-panel-with-title'; +export { getAllBlockInserterItemTitles } from './get-all-block-inserter-item-titles'; export { getAllBlocks } from './get-all-blocks'; export { getAvailableBlockTransforms } from './get-available-block-transforms'; export { getEditedPostContent } from './get-edited-post-content'; @@ -25,7 +26,9 @@ export { isCurrentURL } from './is-current-url'; export { isInDefaultBlock } from './is-in-default-block'; export { loginUser } from './login-user'; export { observeFocusLoss } from './observe-focus-loss'; +export { openAllBlockInserterCategories } from './open-all-block-inserter-categories'; export { openDocumentSettingsSidebar } from './open-document-settings-sidebar'; +export { openGlobalBlockInserter } from './open-global-block-inserter'; export { openPublishPanel } from './open-publish-panel'; export { pressKeyTimes } from './press-key-times'; export { pressKeyWithModifier } from './press-key-with-modifier'; diff --git a/packages/e2e-test-utils/src/open-all-block-inserter-categories.js b/packages/e2e-test-utils/src/open-all-block-inserter-categories.js new file mode 100644 index 0000000000000..d0b70387c9275 --- /dev/null +++ b/packages/e2e-test-utils/src/open-all-block-inserter-categories.js @@ -0,0 +1,11 @@ +/** + * Opens all block inserter categories. + */ +export async function openAllBlockInserterCategories() { + const notOpenCategoryPanels = await page.$$( + '.editor-inserter__results .components-panel__body:not(.is-opened)' + ); + for ( const categoryPanel of notOpenCategoryPanels ) { + await categoryPanel.click(); + } +} diff --git a/packages/e2e-test-utils/src/open-global-block-inserter.js b/packages/e2e-test-utils/src/open-global-block-inserter.js new file mode 100644 index 0000000000000..88fb28703c23d --- /dev/null +++ b/packages/e2e-test-utils/src/open-global-block-inserter.js @@ -0,0 +1,9 @@ +/** + * Opens the global block inserter. + */ +export async function openGlobalBlockInserter() { + await page.click( '.edit-post-header [aria-label="Add block"]' ); + // Waiting here is necessary because sometimes the inserter takes more time to + // render than Puppeteer takes to complete the 'click' action + await page.waitForSelector( '.editor-inserter__menu' ); +} diff --git a/packages/e2e-test-utils/src/search-for-block.js b/packages/e2e-test-utils/src/search-for-block.js index e96b92839221a..bf8b7cd1e74d4 100644 --- a/packages/e2e-test-utils/src/search-for-block.js +++ b/packages/e2e-test-utils/src/search-for-block.js @@ -1,12 +1,14 @@ +/** + * Internal dependencies + */ +import { openGlobalBlockInserter } from './open-global-block-inserter'; + /** * Search for block in the global inserter * * @param {string} searchTerm The text to search the inserter for. */ export async function searchForBlock( searchTerm ) { - await page.click( '.edit-post-header [aria-label="Add block"]' ); - // Waiting here is necessary because sometimes the inserter takes more time to - // render than Puppeteer takes to complete the 'click' action - await page.waitForSelector( '.editor-inserter__menu' ); + await openGlobalBlockInserter(); await page.keyboard.type( searchTerm ); } diff --git a/packages/e2e-tests/plugins/inner-blocks-allowed-blocks.php b/packages/e2e-tests/plugins/inner-blocks-allowed-blocks.php new file mode 100644 index 0000000000000..6448af776825d --- /dev/null +++ b/packages/e2e-tests/plugins/inner-blocks-allowed-blocks.php @@ -0,0 +1,30 @@ + { + beforeEach( async () => { + await createNewPost(); + } ); + + it( 'restricts all blocks inside the columns block', async () => { + await insertBlock( 'Columns' ); + await page.click( '[aria-label="Block Navigation"]' ); + const columnBlockMenuItem = ( await page.$x( '//button[contains(concat(" ", @class, " "), " editor-block-navigation__item-button ")][text()="Column"]' ) )[ 0 ]; + await columnBlockMenuItem.click(); + await openGlobalBlockInserter(); + await openAllBlockInserterCategories(); + expect( await getAllBlockInserterItemTitles() ).toHaveLength( 0 ); + } ); +} ); diff --git a/packages/e2e-tests/specs/blocks/media-text.test.js b/packages/e2e-tests/specs/blocks/media-text.test.js new file mode 100644 index 0000000000000..f9687b3af99cf --- /dev/null +++ b/packages/e2e-tests/specs/blocks/media-text.test.js @@ -0,0 +1,24 @@ +/** + * WordPress dependencies + */ +import { + createNewPost, + getAllBlockInserterItemTitles, + insertBlock, + openAllBlockInserterCategories, + openGlobalBlockInserter, +} from '@wordpress/e2e-test-utils'; + +describe( 'Media Text', () => { + beforeEach( async () => { + await createNewPost(); + } ); + + it( 'restricts blocks that can be inserted', async () => { + await insertBlock( 'Media & Text' ); + await page.click( '.wp-block-media-text .editor-rich-text' ); + await openGlobalBlockInserter(); + await openAllBlockInserterCategories(); + expect( await getAllBlockInserterItemTitles() ).toMatchSnapshot(); + } ); +} ); diff --git a/packages/e2e-tests/specs/plugins/inner-blocks-allowed-blocks.test.js b/packages/e2e-tests/specs/plugins/inner-blocks-allowed-blocks.test.js new file mode 100644 index 0000000000000..7334ccce4f1c8 --- /dev/null +++ b/packages/e2e-tests/specs/plugins/inner-blocks-allowed-blocks.test.js @@ -0,0 +1,59 @@ +/** + * WordPress dependencies + */ +import { + activatePlugin, + createNewPost, + deactivatePlugin, + getAllBlockInserterItemTitles, + insertBlock, + openAllBlockInserterCategories, + openGlobalBlockInserter, +} from '@wordpress/e2e-test-utils'; + +describe( 'Allowed Blocks Setting on InnerBlocks ', () => { + const paragraphSelector = '.editor-rich-text__editable.wp-block-paragraph'; + beforeAll( async () => { + await activatePlugin( 'gutenberg-test-innerblocks-allowed-blocks' ); + } ); + + beforeEach( async () => { + await createNewPost(); + } ); + + afterAll( async () => { + await deactivatePlugin( 'gutenberg-test-innerblocks-allowed-blocks' ); + } ); + + it( 'allows all blocks if the allowed blocks setting was not set', async () => { + const parentBlockSelector = '[data-type="test/allowed-blocks-unset"]'; + const childParagraphSelector = `${ parentBlockSelector } ${ paragraphSelector }`; + await insertBlock( 'Allowed Blocks Unset' ); + await page.waitForSelector( childParagraphSelector ); + await page.click( childParagraphSelector ); + await openGlobalBlockInserter(); + await openAllBlockInserterCategories(); + expect( + ( await getAllBlockInserterItemTitles() ).length + ).toBeGreaterThan( 20 ); + } ); + + it( 'allows the blocks if the allowed blocks setting was set', async () => { + const parentBlockSelector = '[data-type="test/allowed-blocks-set"]'; + const childParagraphSelector = `${ parentBlockSelector } ${ paragraphSelector }`; + await insertBlock( 'Allowed Blocks Set' ); + await page.waitForSelector( childParagraphSelector ); + await page.click( childParagraphSelector ); + await openGlobalBlockInserter(); + await openAllBlockInserterCategories(); + expect( + await getAllBlockInserterItemTitles() + ).toEqual( [ + 'Button', + 'Gallery', + 'List', + 'Media & Text', + 'Quote', + ] ); + } ); +} );