diff --git a/packages/e2e-test-utils/src/press-key-with-modifier.js b/packages/e2e-test-utils/src/press-key-with-modifier.js index b95123d4872201..c36b316cea3ef4 100644 --- a/packages/e2e-test-utils/src/press-key-with-modifier.js +++ b/packages/e2e-test-utils/src/press-key-with-modifier.js @@ -75,7 +75,7 @@ async function emulateSelectAll() { charCode: 0, keyCode: isMac ? 93 : 17, which: isMac ? 93 : 17, - } ), + } ) ); } ); } diff --git a/packages/e2e-tests/specs/editor/blocks/__snapshots__/navigation.test.js.snap b/packages/e2e-tests/specs/editor/blocks/__snapshots__/navigation.test.js.snap new file mode 100644 index 00000000000000..166627ee6e6183 --- /dev/null +++ b/packages/e2e-tests/specs/editor/blocks/__snapshots__/navigation.test.js.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Navigation allows a navigation menu to be created from an empty menu using a mixture of internal and external links 1`] = ` +" + + + +" +`; + +exports[`Navigation allows a navigation menu to be created using existing pages 1`] = ` +" + + + + + +" +`; diff --git a/packages/e2e-tests/specs/editor/blocks/navigation.test.js b/packages/e2e-tests/specs/editor/blocks/navigation.test.js index 7c3d0f26a33e06..bf9efc81bdf0ec 100644 --- a/packages/e2e-tests/specs/editor/blocks/navigation.test.js +++ b/packages/e2e-tests/specs/editor/blocks/navigation.test.js @@ -3,27 +3,143 @@ * WordPress dependencies */ import { + createJSONResponse, createNewPost, + getEditedPostContent, insertBlock, + pressKeyWithModifier, + setUpResponseMocking, } from '@wordpress/e2e-test-utils'; -describe( 'Adds Navigation links', () => { +async function mockPagesResponse( pages ) { + const mappedPages = pages.map( ( { title, slug }, index ) => ( { + id: index + 1, + type: 'page', + link: `https://this/is/a/test/url/${ slug }`, + title: { + rendered: title, + raw: title, + }, + } ) ); + + await setUpResponseMocking( [ + { + match: ( request ) => request.url().includes( `rest_route=${ encodeURIComponent( '/wp/v2/pages' ) }` ), + onRequestMatch: createJSONResponse( mappedPages ), + }, + ] ); +} + +async function mockSearchResponse( items ) { + const mappedItems = items.map( ( { title, slug }, index ) => ( { + id: index + 1, + subtype: 'page', + title, + type: 'post', + url: `https://this/is/a/test/url/${ slug }`, + } ) ); + + await setUpResponseMocking( [ + { + match: ( request ) => request.url().includes( `rest_route=${ encodeURIComponent( '/wp/v2/search' ) }` ), + onRequestMatch: createJSONResponse( mappedItems ), + }, + ] ); +} + +async function updateActiveNavigationLink( { url, label } ) { + if ( url ) { + await page.type( 'input[placeholder="Search or type url"]', url ); + // Wait for the autocomplete suggestion item to appear. + await page.waitForXPath( `//span[@class="block-editor-link-control__search-item-title"]/mark[text()="${ url }"]` ); + await page.keyboard.press( 'Enter' ); + } + + if ( label ) { + await page.click( '.wp-block-navigation-link__content.is-selected' ); + + // Ideally this would be `await pressKeyWithModifier( 'primary', 'a' )` + // to select all text like other tests do. + // Unfortunately, these tests don't seem to pass on Travis CI when + // using that approach, while using `Home` and `End` they do pass. + await page.keyboard.press( 'Home' ); + await pressKeyWithModifier( 'shift', 'End' ); + await page.keyboard.press( 'Backspace' ); + await page.keyboard.type( label ); + } +} + +describe( 'Navigation', () => { beforeEach( async () => { await createNewPost(); } ); - it( 'Should add a link with one click', async () => { + it( 'allows a navigation menu to be created using existing pages', async () => { + // Mock the response from the Pages endpoint. This is done so that the pages returned are always + // consistent and to test the feature more rigorously than the single default sample page. + await mockPagesResponse( [ + { + title: 'Home', + slug: 'home', + }, + { + title: 'About', + slug: 'about', + }, + { + title: 'Contact Us', + slug: 'contact', + }, + ] ); + + // Add the navigation block. + await insertBlock( 'Navigation' ); + + // Create an empty nav block. The 'create' button is disabled until pages are loaded, + // so we must wait for it to become not-disabled. + await page.waitForXPath( '//button[text()="Create from all top-level pages"][not(@disabled)]' ); + const [ createFromExistingButton ] = await page.$x( '//button[text()="Create from all top-level pages"][not(@disabled)]' ); + await createFromExistingButton.click(); + + // Snapshot should contain the mocked pages. + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); + + it( 'allows a navigation menu to be created from an empty menu using a mixture of internal and external links', async () => { + // Add the navigation block. await insertBlock( 'Navigation' ); + + // Create an empty nav block. + await page.waitForSelector( '.wp-block-navigation-placeholder' ); const [ createEmptyButton ] = await page.$x( '//button[text()="Create empty"]' ); await createEmptyButton.click(); - await page.waitForSelector( 'input[placeholder="Search or type url"]' ); - await page.type( 'input[placeholder="Search or type url"]', 'http://example.com' ); - await page.keyboard.press( 'Enter' ); + // Add a link to the default Navigation Link block. + await updateActiveNavigationLink( { url: 'https://wordpress.org', label: 'WP' } ); + + // Move the mouse to reveal the block movers. Without this the test seems to fail. + await page.mouse.move( 100, 100 ); + + // Add another Navigation Link block. + // Using 'click' here checks for regressions of https://github.com/WordPress/gutenberg/issues/18329, + // an issue where the block appender requires two clicks. await page.click( '.wp-block-navigation .block-list-appender' ); - const navigationLinkCount = await page.$$eval( '.wp-block-navigation-link', ( navigationLinks ) => navigationLinks.length ); + // For the second nav link block use an existing internal page. + // Mock the api response so that it's consistent. + await mockSearchResponse( [ { title: 'Contact Us', slug: 'contact-us' } ] ); + + // Add a link to the default Navigation Link block. + await updateActiveNavigationLink( { url: 'Contact Us', label: 'Get in touch' } ); + + // Expect a Navigation Block with two Navigation Links in the snapshot. + expect( await getEditedPostContent() ).toMatchSnapshot(); - expect( navigationLinkCount ).toBe( 2 ); + // TODO - this is needed currently because when adding a link using the suggestion list, + // a submit button is used. The form that the submit button is in is unmounted when submission + // occurs, resulting in a warning 'Form submission canceled because the form is not connected' + // in Chrome. + // Ideally, the suggestions wouldn't be implemented using submit buttons. + expect( console ).toHaveWarned(); } ); } );