From ad959db6f3ee70dff1734d45892b52249e64998f Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 29 Mar 2023 10:25:20 +0100 Subject: [PATCH 01/20] Scaffold initial test --- .../specs/editor/blocks/navigation.spec.js | 55 +++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 5a002f5324c4ee..76e9297d5c3637 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -3,7 +3,9 @@ */ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); -test.describe( 'As a user I want the navigation block to fallback to the best possible default', () => { +const { describe } = test; + +describe( 'As a user I want the navigation block to fallback to the best possible default', () => { test.beforeAll( async ( { requestUtils } ) => { //TT3 is preferable to emptytheme because it already has the navigation block on its templates. await requestUtils.activateTheme( 'twentytwentythree' ); @@ -175,7 +177,7 @@ test.describe( 'As a user I want the navigation block to fallback to the best po } ); } ); -test.describe( 'As a user I want to create submenus using the navigation block', () => { +describe( 'As a user I want to create submenus using the navigation block', () => { test.beforeAll( async ( { requestUtils } ) => { //TT3 is preferable to emptytheme because it already has the navigation block on its templates. await requestUtils.activateTheme( 'twentytwentythree' ); @@ -281,8 +283,8 @@ test.describe( 'As a user I want to create submenus using the navigation block', } ); } ); -test.describe( 'Navigation block', () => { - test.describe( 'As a user I want to see a warning if the menu referenced by a navigation block is not available', () => { +describe( 'Navigation block', () => { + describe( 'As a user I want to see a warning if the menu referenced by a navigation block is not available', () => { test.beforeEach( async ( { admin } ) => { await admin.createNewPost(); } ); @@ -317,3 +319,48 @@ test.describe( 'Navigation block', () => { } ); } ); } ); + +describe.only( 'List view editing', () => { + test( 'it should show a list view in the inspector controls', async ( { + admin, + page, + editor, + requestUtils, + } ) => { + await admin.createNewPost(); + await requestUtils.createNavigationMenu( { + title: 'Test Menu', + content: + '', + } ); + + await editor.insertBlock( { name: 'core/navigation' } ); + + await editor.openDocumentSettingsSidebar(); + + const listViewTab = page.getByRole( 'tab', { + name: 'List View', + } ); + + await listViewTab.click(); + + const listViewPanel = page.getByRole( 'tabpanel', { + name: 'List View', + } ); + + await expect( listViewPanel ).toBeVisible(); + + await expect( + listViewPanel.getByRole( 'heading', { + name: 'Menu', + } ) + ).toBeVisible(); + + await expect( + listViewPanel.getByRole( 'treegrid', { + name: 'Block navigation structure', + description: 'Structure for navigation menu: Test Menu', + } ) + ).toBeVisible(); + } ); +} ); From 8ddd70bf9b7c55b37478da90913f48559bf5b329 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 29 Mar 2023 11:12:21 +0100 Subject: [PATCH 02/20] Assert on menu structure --- .../specs/editor/blocks/navigation.spec.js | 61 ++++++++++++++++++- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 76e9297d5c3637..c8add422a26e6f 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -320,7 +320,7 @@ describe( 'Navigation block', () => { } ); } ); -describe.only( 'List view editing', () => { +describe( 'List view editing', () => { test( 'it should show a list view in the inspector controls', async ( { admin, page, @@ -330,8 +330,10 @@ describe.only( 'List view editing', () => { await admin.createNewPost(); await requestUtils.createNavigationMenu( { title: 'Test Menu', - content: - '', + content: ` + + + `, } ); await editor.insertBlock( { name: 'core/navigation' } ); @@ -363,4 +365,57 @@ describe.only( 'List view editing', () => { } ) ).toBeVisible(); } ); + + test.only( `list view should correctly reflect navigation items' structure`, async ( { + admin, + page, + editor, + requestUtils, + } ) => { + await admin.createNewPost(); + await requestUtils.createNavigationMenu( { + title: 'Test Menu', + content: ` + + + `, + } ); + + await editor.insertBlock( { name: 'core/navigation' } ); + + await editor.openDocumentSettingsSidebar(); + + const listViewTab = page.getByRole( 'tab', { + name: 'List View', + } ); + + await listViewTab.click(); + + const listView = page.getByRole( 'treegrid', { + name: 'Block navigation structure', + description: 'Structure for navigation menu: Test Menu', + } ); + + // Check the structure of the individual menu items matches the one that was created. + await expect( + listView.getByRole( 'gridcell' ).filter( { + hasText: 'Block 1 of 2, Level 1', // proxy for filtering by description. + has: page.getByText( 'Top Level Item 1' ), // find the hidden anchor with the label of the Nav item. + } ) + ).toBeVisible(); + + await expect( + listView.getByRole( 'gridcell' ).filter( { + hasText: 'Block 2 of 2, Level 1', // proxy for filtering by description. + has: page.getByText( 'Top Level Item 2' ), // find the hidden anchor with the label of the Nav item. + } ) + ).toBeVisible(); + + await expect( + listView.getByRole( 'gridcell' ).filter( { + hasText: 'Block 1 of 1, Level 2', // proxy for filtering by description. + has: page.getByText( 'Test Submenu Item' ), // find the hidden anchor with the label of the Nav item. + } ) + ).toBeVisible(); + } ); } ); From 4982591349ec73c15144f7ee7197de1bea7f665f Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 29 Mar 2023 11:17:43 +0100 Subject: [PATCH 03/20] Refine structure test filters --- .../specs/editor/blocks/navigation.spec.js | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index c8add422a26e6f..8879f2f0a91e98 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -398,24 +398,30 @@ describe( 'List view editing', () => { // Check the structure of the individual menu items matches the one that was created. await expect( - listView.getByRole( 'gridcell' ).filter( { - hasText: 'Block 1 of 2, Level 1', // proxy for filtering by description. - has: page.getByText( 'Top Level Item 1' ), // find the hidden anchor with the label of the Nav item. - } ) + listView + .getByRole( 'gridcell' ) + .filter( { + hasText: 'Block 1 of 2, Level 1', // proxy for filtering by description. + } ) + .getByText( 'Top Level Item 1' ) ).toBeVisible(); await expect( - listView.getByRole( 'gridcell' ).filter( { - hasText: 'Block 2 of 2, Level 1', // proxy for filtering by description. - has: page.getByText( 'Top Level Item 2' ), // find the hidden anchor with the label of the Nav item. - } ) + listView + .getByRole( 'gridcell' ) + .filter( { + hasText: 'Block 2 of 2, Level 1', // proxy for filtering by description. + } ) + .getByText( 'Top Level Item 2' ) ).toBeVisible(); await expect( - listView.getByRole( 'gridcell' ).filter( { - hasText: 'Block 1 of 1, Level 2', // proxy for filtering by description. - has: page.getByText( 'Test Submenu Item' ), // find the hidden anchor with the label of the Nav item. - } ) + listView + .getByRole( 'gridcell' ) + .filter( { + hasText: 'Block 1 of 1, Level 2', // proxy for filtering by description. + } ) + .getByText( 'Test Submenu Item' ) ).toBeVisible(); } ); } ); From 6eb7c5961064456edddc439bf666de181b312131 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 29 Mar 2023 11:44:21 +0100 Subject: [PATCH 04/20] Assert using appender to add menu items --- .../specs/editor/blocks/navigation.spec.js | 103 +++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 8879f2f0a91e98..dcd0a37059554b 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -366,7 +366,7 @@ describe( 'List view editing', () => { ).toBeVisible(); } ); - test.only( `list view should correctly reflect navigation items' structure`, async ( { + test( `list view should correctly reflect navigation items' structure`, async ( { admin, page, editor, @@ -424,4 +424,105 @@ describe( 'List view editing', () => { .getByText( 'Test Submenu Item' ) ).toBeVisible(); } ); + + test.only( `can add new menu items`, async ( { + admin, + page, + editor, + requestUtils, + } ) => { + await admin.createNewPost(); + await requestUtils.createNavigationMenu( { + title: 'Test Menu', + content: ` + + + `, + } ); + + await editor.insertBlock( { name: 'core/navigation' } ); + + await editor.openDocumentSettingsSidebar(); + + const listViewTab = page.getByRole( 'tab', { + name: 'List View', + } ); + + await listViewTab.click(); + + const listView = page.getByRole( 'treegrid', { + name: 'Block navigation structure', + description: 'Structure for navigation menu: Test Menu', + } ); + + const appender = listView.getByRole( 'button', { + name: 'Add block', + } ); + + await expect( appender ).toBeVisible(); + + await appender.click(); + + // Expect to see the block inserter. + await expect( + page.getByRole( 'searchbox', { + name: 'Search for blocks and patterns', + } ) + ).toBeFocused(); + + const blockResults = page.getByRole( 'listbox', { + name: 'Blocks', + } ); + + await expect( blockResults ).toBeVisible(); + + const pageLinkBlock = blockResults.getByRole( 'option', { + name: 'Page Link', + } ); + + await expect( pageLinkBlock ).toBeVisible(); + + const customLinkBlock = blockResults.getByRole( 'option', { + name: 'Custom Link', + } ); + + await expect( customLinkBlock ).toBeVisible(); + + await pageLinkBlock.click(); + + // Expect to see the Link creation UI. + const linkUIInput = page.getByRole( 'combobox', { + name: 'URL', + } ); + + await expect( linkUIInput ).toBeFocused(); + + const linkUIResults = page.getByRole( 'listbox', { + name: 'Recently updated', + } ); + + await expect( linkUIResults ).toBeVisible(); + + // click on the first result + const firstResult = linkUIResults.getByRole( 'option' ).nth( 0 ); + + // Grab the text from the first result so we can check it was inserted. + const firstResultText = await firstResult + .locator( '.block-editor-link-control__search-item-title' ) // this is the only way to get the label text without the URL. + .innerText(); + + await firstResult.click(); + + // check the new menu item was inserted at the end of the existing menu. + await expect( + listView + .getByRole( 'gridcell', { + name: 'Page Link link', + } ) + .filter( { + hasText: 'Block 3 of 3, Level 1', // proxy for filtering by description. + } ) + .getByText( firstResultText ) + ).toBeVisible(); + } ); } ); From 2a867f9e758fed2779e83cf9ee0ec9a957a106c8 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 29 Mar 2023 11:46:16 +0100 Subject: [PATCH 05/20] Improve assertions to check the type of the link being inserted --- test/e2e/specs/editor/blocks/navigation.spec.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index dcd0a37059554b..95857e59e63e3a 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -320,7 +320,7 @@ describe( 'Navigation block', () => { } ); } ); -describe( 'List view editing', () => { +describe.only( 'List view editing', () => { test( 'it should show a list view in the inspector controls', async ( { admin, page, @@ -399,7 +399,9 @@ describe( 'List view editing', () => { // Check the structure of the individual menu items matches the one that was created. await expect( listView - .getByRole( 'gridcell' ) + .getByRole( 'gridcell', { + name: 'Page Link link', + } ) .filter( { hasText: 'Block 1 of 2, Level 1', // proxy for filtering by description. } ) @@ -408,7 +410,9 @@ describe( 'List view editing', () => { await expect( listView - .getByRole( 'gridcell' ) + .getByRole( 'gridcell', { + name: 'Submenu link', + } ) .filter( { hasText: 'Block 2 of 2, Level 1', // proxy for filtering by description. } ) @@ -417,7 +421,9 @@ describe( 'List view editing', () => { await expect( listView - .getByRole( 'gridcell' ) + .getByRole( 'gridcell', { + name: 'Page Link link', + } ) .filter( { hasText: 'Block 1 of 1, Level 2', // proxy for filtering by description. } ) @@ -425,7 +431,7 @@ describe( 'List view editing', () => { ).toBeVisible(); } ); - test.only( `can add new menu items`, async ( { + test( `can add new menu items`, async ( { admin, page, editor, From cfc3e67a3e77a4be49a5e63d8beebc8548d366b1 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 29 Mar 2023 11:55:16 +0100 Subject: [PATCH 06/20] Improve asserting on Page and Custom links being 1st and 2nd results --- .../specs/editor/blocks/navigation.spec.js | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 95857e59e63e3a..49a4d4b15225de 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -320,7 +320,7 @@ describe( 'Navigation block', () => { } ); } ); -describe.only( 'List view editing', () => { +describe( 'List view editing', () => { test( 'it should show a list view in the inspector controls', async ( { admin, page, @@ -431,7 +431,7 @@ describe.only( 'List view editing', () => { ).toBeVisible(); } ); - test( `can add new menu items`, async ( { + test.only( `can add new menu items`, async ( { admin, page, editor, @@ -482,25 +482,21 @@ describe.only( 'List view editing', () => { await expect( blockResults ).toBeVisible(); - const pageLinkBlock = blockResults.getByRole( 'option', { - name: 'Page Link', - } ); - - await expect( pageLinkBlock ).toBeVisible(); + const blockResultOptions = blockResults.getByRole( 'option' ); - const customLinkBlock = blockResults.getByRole( 'option', { - name: 'Custom Link', - } ); + // Expect to see the Page Link and Custom Link blocks as the nth(0) and nth(1) results. + // This is important for usability as the Page Link block is the most likely to be used. + await expect( blockResultOptions.nth( 0 ) ).toHaveText( 'Page Link' ); + await expect( blockResultOptions.nth( 1 ) ).toHaveText( 'Custom Link' ); - await expect( customLinkBlock ).toBeVisible(); + // Select the Page Link option. + const pageLinkResult = blockResultOptions.nth( 0 ); + await pageLinkResult.click(); - await pageLinkBlock.click(); - - // Expect to see the Link creation UI. + // Expect to see the Link creation UI be focused. const linkUIInput = page.getByRole( 'combobox', { name: 'URL', } ); - await expect( linkUIInput ).toBeFocused(); const linkUIResults = page.getByRole( 'listbox', { From 9c0b817b48765ed9a8e412f43ca936f0d77e865a Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 29 Mar 2023 14:04:13 +0100 Subject: [PATCH 07/20] Test block removal --- .../specs/editor/blocks/navigation.spec.js | 86 ++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 49a4d4b15225de..d15b0295124ed4 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -431,7 +431,7 @@ describe( 'List view editing', () => { ).toBeVisible(); } ); - test.only( `can add new menu items`, async ( { + test( `can add new menu items`, async ( { admin, page, editor, @@ -513,9 +513,10 @@ describe( 'List view editing', () => { .locator( '.block-editor-link-control__search-item-title' ) // this is the only way to get the label text without the URL. .innerText(); + // Create the link. await firstResult.click(); - // check the new menu item was inserted at the end of the existing menu. + // Check the new menu item was inserted at the end of the existing menu. await expect( listView .getByRole( 'gridcell', { @@ -527,4 +528,85 @@ describe( 'List view editing', () => { .getByText( firstResultText ) ).toBeVisible(); } ); + + test( `can remove menu items`, async ( { + admin, + page, + editor, + requestUtils, + } ) => { + await admin.createNewPost(); + await requestUtils.createNavigationMenu( { + title: 'Test Menu', + content: ` + + + `, + } ); + + await editor.insertBlock( { name: 'core/navigation' } ); + + await editor.openDocumentSettingsSidebar(); + + const listViewTab = page.getByRole( 'tab', { + name: 'List View', + } ); + + await listViewTab.click(); + + const listView = page.getByRole( 'treegrid', { + name: 'Block navigation structure', + description: 'Structure for navigation menu: Test Menu', + } ); + + // click on options menu for the first menu item and select remove. + const firstMenuItem = listView + .getByRole( 'gridcell', { + name: 'Page Link link', + } ) + .filter( { + hasText: 'Block 1 of 2, Level 1', // proxy for filtering by description. + } ); + + // Focus the node to reveal the "3 dots" options menu button. + const firstMenuItemAnchor = listView.getByRole( 'link', { + name: 'Top Level Item 1', + includeHidden: true, + } ); + await firstMenuItemAnchor.focus(); + + // The options menu button is a sibling of the menu item gridcell. + const firstItemOptions = firstMenuItem + .locator( '..' ) // parent selector. + .getByRole( 'button', { + name: 'Options for Page Link block', + } ); + + // Open the options menu. + await firstItemOptions.click(); + + // usage of `page` is required because the options menu is rendered into a slot + // outside of the treegrid. + const removeBlockOption = page + .getByRole( 'menu', { + name: 'Options for Page Link block', + } ) + .getByRole( 'menuitem', { + name: 'Remove Top Level Item 1', + } ); + + await removeBlockOption.click(); + + // Check the menu item was removed. + await expect( + listView + .getByRole( 'gridcell', { + name: 'Page Link link', + } ) + .filter( { + hasText: 'Block 1 of 1, Level 1', // proxy for filtering by description. + } ) + .getByText( 'Top Level Item 1' ) + ).not.toBeVisible(); + } ); } ); From d278f0c207fe1e2427060d833686f65a8f0b261f Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 29 Mar 2023 14:04:54 +0100 Subject: [PATCH 08/20] Make test describe blocks consistent with other tests --- test/e2e/specs/editor/blocks/navigation.spec.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index d15b0295124ed4..8bc50cb2f2a40b 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -3,9 +3,7 @@ */ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); -const { describe } = test; - -describe( 'As a user I want the navigation block to fallback to the best possible default', () => { +test.describe( 'As a user I want the navigation block to fallback to the best possible default', () => { test.beforeAll( async ( { requestUtils } ) => { //TT3 is preferable to emptytheme because it already has the navigation block on its templates. await requestUtils.activateTheme( 'twentytwentythree' ); @@ -177,7 +175,7 @@ describe( 'As a user I want the navigation block to fallback to the best possibl } ); } ); -describe( 'As a user I want to create submenus using the navigation block', () => { +test.describe( 'As a user I want to create submenus using the navigation block', () => { test.beforeAll( async ( { requestUtils } ) => { //TT3 is preferable to emptytheme because it already has the navigation block on its templates. await requestUtils.activateTheme( 'twentytwentythree' ); @@ -283,8 +281,8 @@ describe( 'As a user I want to create submenus using the navigation block', () = } ); } ); -describe( 'Navigation block', () => { - describe( 'As a user I want to see a warning if the menu referenced by a navigation block is not available', () => { +test.describe( 'Navigation block', () => { + test.describe( 'As a user I want to see a warning if the menu referenced by a navigation block is not available', () => { test.beforeEach( async ( { admin } ) => { await admin.createNewPost(); } ); @@ -320,7 +318,7 @@ describe( 'Navigation block', () => { } ); } ); -describe( 'List view editing', () => { +test.describe( 'List view editing', () => { test( 'it should show a list view in the inspector controls', async ( { admin, page, From 1d4a60076351705919f3414d3e7a59718c168fd3 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 29 Mar 2023 14:15:40 +0100 Subject: [PATCH 09/20] Add test for editing items --- .../specs/editor/blocks/navigation.spec.js | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 8bc50cb2f2a40b..f5143d2e5defc2 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -607,4 +607,86 @@ test.describe( 'List view editing', () => { .getByText( 'Top Level Item 1' ) ).not.toBeVisible(); } ); + + test( `can edit menu items`, async ( { + admin, + page, + editor, + requestUtils, + } ) => { + await admin.createNewPost(); + await requestUtils.createNavigationMenu( { + title: 'Test Menu', + content: ` + + + `, + } ); + + await editor.insertBlock( { name: 'core/navigation' } ); + + await editor.openDocumentSettingsSidebar(); + + const listViewTab = page.getByRole( 'tab', { + name: 'List View', + } ); + + await listViewTab.click(); + + const listView = page.getByRole( 'treegrid', { + name: 'Block navigation structure', + description: 'Structure for navigation menu: Test Menu', + } ); + + // Click on the first menu item to open its settings. + const firstMenuItemAnchor = listView.getByRole( 'link', { + name: 'Top Level Item 1', + includeHidden: true, + } ); + await firstMenuItemAnchor.click(); + + // Get the settings panel. + const blockSettings = page.getByRole( 'region', { + name: 'Editor settings', + } ); + + await expect( blockSettings ).toBeVisible(); + + await expect( + blockSettings.getByRole( 'heading', { + name: 'Page Link', + } ) + ).toBeVisible(); + + await expect( + blockSettings.getByRole( 'tab', { + name: 'Settings', + selected: true, + } ) + ).toBeVisible(); + + await expect( + blockSettings + .getByRole( 'tabpanel', { + name: 'Settings', + } ) + .getByRole( 'heading', { + name: 'Link Settings', + } ) + ).toBeVisible(); + + // Click the back button to go back to the Nav block. + await blockSettings + .getByRole( 'button', { + name: 'Go to parent Navigation block', + } ) + .click(); + + // Check we're back on the Nav block list view. + const listViewPanel = page.getByRole( 'tabpanel', { + name: 'List View', + } ); + + await expect( listViewPanel ).toBeVisible(); + } ); } ); From 30b4e54d145618d5537a32a24491af4700709e3f Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 29 Mar 2023 14:28:07 +0100 Subject: [PATCH 10/20] Test for adding submenus --- .../specs/editor/blocks/navigation.spec.js | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index f5143d2e5defc2..2bd587f471b2eb 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -689,4 +689,108 @@ test.describe( 'List view editing', () => { await expect( listViewPanel ).toBeVisible(); } ); + + test( `can add submenus`, async ( { + admin, + page, + editor, + requestUtils, + } ) => { + await admin.createNewPost(); + await requestUtils.createNavigationMenu( { + title: 'Test Menu', + content: ` + + + `, + } ); + + await editor.insertBlock( { name: 'core/navigation' } ); + + await editor.openDocumentSettingsSidebar(); + + const listViewTab = page.getByRole( 'tab', { + name: 'List View', + } ); + + await listViewTab.click(); + + const listView = page.getByRole( 'treegrid', { + name: 'Block navigation structure', + description: 'Structure for navigation menu: Test Menu', + } ); + + // click on options menu for the first menu item and select remove. + const firstMenuItem = listView + .getByRole( 'gridcell', { + name: 'Page Link link', + } ) + .filter( { + hasText: 'Block 1 of 2, Level 1', // proxy for filtering by description. + } ); + + // Focus the node to reveal the "3 dots" options menu button. + const firstMenuItemAnchor = listView.getByRole( 'link', { + name: 'Top Level Item 1', + includeHidden: true, + } ); + await firstMenuItemAnchor.focus(); + + // The options menu button is a sibling of the menu item gridcell. + const firstItemOptions = firstMenuItem + .locator( '..' ) // parent selector. + .getByRole( 'button', { + name: 'Options for Page Link block', + } ); + + // Open the options menu. + await firstItemOptions.click(); + + // Add the submenu. + // usage of `page` is required because the options menu is rendered into a slot + // outside of the treegrid. + const addSubmenuOption = page + .getByRole( 'menu', { + name: 'Options for Page Link block', + } ) + .getByRole( 'menuitem', { + name: 'Add submenu link', + } ); + + await addSubmenuOption.click(); + + const linkUIInput = page.getByRole( 'combobox', { + name: 'URL', + } ); + await expect( linkUIInput ).toBeFocused(); + + await page.keyboard.type( 'https://wordpress.org/' ); + + await page.keyboard.press( 'Enter' ); + + // Check the new item was inserted in the correct place. + await expect( + listView + .getByRole( 'gridcell', { + name: 'Custom Link link', + } ) + .filter( { + hasText: 'Block 1 of 1, Level 2', // proxy for filtering by description. + } ) + .getByText( 'wordpress.org' ) + ).toBeVisible(); + + // Check that the original item is still there but that it is now + // a submenu item. + await expect( + listView + .getByRole( 'gridcell', { + name: 'Submenu link', + } ) + .filter( { + hasText: 'Block 1 of 2, Level 1', // proxy for filtering by description. + } ) + .getByText( 'Top Level Item 1' ) + ).toBeVisible(); + } ); } ); From 1a067022477e76ce0132b7fdb8217c72b1104424 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 30 Mar 2023 09:27:17 +0100 Subject: [PATCH 11/20] Remove uneccessary test wording --- test/e2e/specs/editor/blocks/navigation.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 2bd587f471b2eb..bce173812a70c9 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -319,7 +319,7 @@ test.describe( 'Navigation block', () => { } ); test.describe( 'List view editing', () => { - test( 'it should show a list view in the inspector controls', async ( { + test( 'show a list view in the inspector controls', async ( { admin, page, editor, From b576358224b44417af7254152b7e90d74c3b8d2e Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 30 Mar 2023 09:30:40 +0100 Subject: [PATCH 12/20] Remove unecessary click on List View tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Should be visible by default. Left one test which will fail if the tab isn’t automatically pre-selected. --- .../specs/editor/blocks/navigation.spec.js | 40 +++---------------- 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index bce173812a70c9..689907d0ae83d3 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -338,11 +338,11 @@ test.describe( 'List view editing', () => { await editor.openDocumentSettingsSidebar(); - const listViewTab = page.getByRole( 'tab', { - name: 'List View', - } ); - - await listViewTab.click(); + await expect( + page.getByRole( 'tab', { + name: 'List View', + } ) + ).toBeVisible(); const listViewPanel = page.getByRole( 'tabpanel', { name: 'List View', @@ -383,12 +383,6 @@ test.describe( 'List view editing', () => { await editor.openDocumentSettingsSidebar(); - const listViewTab = page.getByRole( 'tab', { - name: 'List View', - } ); - - await listViewTab.click(); - const listView = page.getByRole( 'treegrid', { name: 'Block navigation structure', description: 'Structure for navigation menu: Test Menu', @@ -448,12 +442,6 @@ test.describe( 'List view editing', () => { await editor.openDocumentSettingsSidebar(); - const listViewTab = page.getByRole( 'tab', { - name: 'List View', - } ); - - await listViewTab.click(); - const listView = page.getByRole( 'treegrid', { name: 'Block navigation structure', description: 'Structure for navigation menu: Test Menu', @@ -546,12 +534,6 @@ test.describe( 'List view editing', () => { await editor.openDocumentSettingsSidebar(); - const listViewTab = page.getByRole( 'tab', { - name: 'List View', - } ); - - await listViewTab.click(); - const listView = page.getByRole( 'treegrid', { name: 'Block navigation structure', description: 'Structure for navigation menu: Test Menu', @@ -627,12 +609,6 @@ test.describe( 'List view editing', () => { await editor.openDocumentSettingsSidebar(); - const listViewTab = page.getByRole( 'tab', { - name: 'List View', - } ); - - await listViewTab.click(); - const listView = page.getByRole( 'treegrid', { name: 'Block navigation structure', description: 'Structure for navigation menu: Test Menu', @@ -709,12 +685,6 @@ test.describe( 'List view editing', () => { await editor.openDocumentSettingsSidebar(); - const listViewTab = page.getByRole( 'tab', { - name: 'List View', - } ); - - await listViewTab.click(); - const listView = page.getByRole( 'treegrid', { name: 'Block navigation structure', description: 'Structure for navigation menu: Test Menu', From 6e864889df281f5adbb072ce13eafbadbd3deddb Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 30 Mar 2023 09:34:50 +0100 Subject: [PATCH 13/20] Extract blocks to a var --- .../specs/editor/blocks/navigation.spec.js | 56 +++++-------------- 1 file changed, 14 insertions(+), 42 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 689907d0ae83d3..1e076b0b7adfc6 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -319,6 +319,14 @@ test.describe( 'Navigation block', () => { } ); test.describe( 'List view editing', () => { + const navMenuBlocksFixture = { + title: 'Test Menu', + content: ` + + + `, + }; + test( 'show a list view in the inspector controls', async ( { admin, page, @@ -326,13 +334,7 @@ test.describe( 'List view editing', () => { requestUtils, } ) => { await admin.createNewPost(); - await requestUtils.createNavigationMenu( { - title: 'Test Menu', - content: ` - - - `, - } ); + await requestUtils.createNavigationMenu( navMenuBlocksFixture ); await editor.insertBlock( { name: 'core/navigation' } ); @@ -371,13 +373,7 @@ test.describe( 'List view editing', () => { requestUtils, } ) => { await admin.createNewPost(); - await requestUtils.createNavigationMenu( { - title: 'Test Menu', - content: ` - - - `, - } ); + await requestUtils.createNavigationMenu( navMenuBlocksFixture ); await editor.insertBlock( { name: 'core/navigation' } ); @@ -430,13 +426,7 @@ test.describe( 'List view editing', () => { requestUtils, } ) => { await admin.createNewPost(); - await requestUtils.createNavigationMenu( { - title: 'Test Menu', - content: ` - - - `, - } ); + await requestUtils.createNavigationMenu( navMenuBlocksFixture ); await editor.insertBlock( { name: 'core/navigation' } ); @@ -522,13 +512,7 @@ test.describe( 'List view editing', () => { requestUtils, } ) => { await admin.createNewPost(); - await requestUtils.createNavigationMenu( { - title: 'Test Menu', - content: ` - - - `, - } ); + await requestUtils.createNavigationMenu( navMenuBlocksFixture ); await editor.insertBlock( { name: 'core/navigation' } ); @@ -597,13 +581,7 @@ test.describe( 'List view editing', () => { requestUtils, } ) => { await admin.createNewPost(); - await requestUtils.createNavigationMenu( { - title: 'Test Menu', - content: ` - - - `, - } ); + await requestUtils.createNavigationMenu( navMenuBlocksFixture ); await editor.insertBlock( { name: 'core/navigation' } ); @@ -673,13 +651,7 @@ test.describe( 'List view editing', () => { requestUtils, } ) => { await admin.createNewPost(); - await requestUtils.createNavigationMenu( { - title: 'Test Menu', - content: ` - - - `, - } ); + await requestUtils.createNavigationMenu( navMenuBlocksFixture ); await editor.insertBlock( { name: 'core/navigation' } ); From 9d6bddbc25a8623d4bbfdccdd93f1bfef9969435 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 30 Mar 2023 10:56:46 +0100 Subject: [PATCH 14/20] Add Link Control test helper and extract relevant portions of tests --- .../specs/editor/blocks/navigation.spec.js | 70 ++++++++++++++----- 1 file changed, 53 insertions(+), 17 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 1e076b0b7adfc6..12f59e5cf8a91d 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -327,6 +327,12 @@ test.describe( 'List view editing', () => { `, }; + test.use( { + linkControl: async ( { page }, use ) => { + await use( new LinkControl( { page } ) ); + }, + } ); + test( 'show a list view in the inspector controls', async ( { admin, page, @@ -424,6 +430,7 @@ test.describe( 'List view editing', () => { page, editor, requestUtils, + linkControl, } ) => { await admin.createNewPost(); await requestUtils.createNavigationMenu( navMenuBlocksFixture ); @@ -470,19 +477,11 @@ test.describe( 'List view editing', () => { await pageLinkResult.click(); // Expect to see the Link creation UI be focused. - const linkUIInput = page.getByRole( 'combobox', { - name: 'URL', - } ); - await expect( linkUIInput ).toBeFocused(); - - const linkUIResults = page.getByRole( 'listbox', { - name: 'Recently updated', - } ); + const linkUIInput = linkControl.getSearchInput(); - await expect( linkUIResults ).toBeVisible(); + await expect( linkUIInput ).toBeFocused(); - // click on the first result - const firstResult = linkUIResults.getByRole( 'option' ).nth( 0 ); + const firstResult = await linkControl.getNthSearchResult( 0 ); // Grab the text from the first result so we can check it was inserted. const firstResultText = await firstResult @@ -649,6 +648,7 @@ test.describe( 'List view editing', () => { page, editor, requestUtils, + linkControl, } ) => { await admin.createNewPost(); await requestUtils.createNavigationMenu( navMenuBlocksFixture ); @@ -701,12 +701,7 @@ test.describe( 'List view editing', () => { await addSubmenuOption.click(); - const linkUIInput = page.getByRole( 'combobox', { - name: 'URL', - } ); - await expect( linkUIInput ).toBeFocused(); - - await page.keyboard.type( 'https://wordpress.org/' ); + await linkControl.searchFor( 'https://wordpress.org' ); await page.keyboard.press( 'Enter' ); @@ -736,3 +731,44 @@ test.describe( 'List view editing', () => { ).toBeVisible(); } ); } ); + +class LinkControl { + constructor( { page } ) { + this.page = page; + } + + getSearchInput() { + return this.page.getByRole( 'combobox', { + name: 'URL', + } ); + } + + async getSearchResults() { + const searchInput = this.getSearchInput(); + + const resultsRef = await searchInput.getAttribute( 'aria-owns' ); + + const linkUIResults = this.page.locator( `#${ resultsRef }` ); + + await expect( linkUIResults ).toBeVisible(); + + return linkUIResults.getByRole( 'option' ); + } + + async getNthSearchResult( index = 0 ) { + const results = await this.getSearchResults(); + return results.nth( index ); + } + + async searchFor( searchTerm = 'https://wordpress.org' ) { + const input = this.getSearchInput(); + + await expect( input ).toBeFocused(); + + await this.page.keyboard.type( searchTerm ); + + await expect( input ).toHaveValue( searchTerm ); + + return input; + } +} From 7bcfb0315e0869f8848e46d73447a456522efa36 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 30 Mar 2023 11:02:26 +0100 Subject: [PATCH 15/20] Extract util for getting result text --- test/e2e/specs/editor/blocks/navigation.spec.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 12f59e5cf8a91d..e6fccd8a53d6a6 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -484,9 +484,9 @@ test.describe( 'List view editing', () => { const firstResult = await linkControl.getNthSearchResult( 0 ); // Grab the text from the first result so we can check it was inserted. - const firstResultText = await firstResult - .locator( '.block-editor-link-control__search-item-title' ) // this is the only way to get the label text without the URL. - .innerText(); + const firstResultText = await linkControl.getSearchResultText( + firstResult + ); // Create the link. await firstResult.click(); @@ -771,4 +771,12 @@ class LinkControl { return input; } + + async getSearchResultText( result ) { + await expect( result ).toBeVisible(); + + return result + .locator( '.block-editor-link-control__search-item-title' ) // this is the only way to get the label text without the URL. + .innerText(); + } } From cd36c1aaaa9d377c28e2e14840716a9c7e9badd1 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 30 Mar 2023 11:14:12 +0100 Subject: [PATCH 16/20] Remove unneeded focus of item to trigger options menu --- test/e2e/specs/editor/blocks/navigation.spec.js | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index e6fccd8a53d6a6..d4f96ebdffae00 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -531,13 +531,6 @@ test.describe( 'List view editing', () => { hasText: 'Block 1 of 2, Level 1', // proxy for filtering by description. } ); - // Focus the node to reveal the "3 dots" options menu button. - const firstMenuItemAnchor = listView.getByRole( 'link', { - name: 'Top Level Item 1', - includeHidden: true, - } ); - await firstMenuItemAnchor.focus(); - // The options menu button is a sibling of the menu item gridcell. const firstItemOptions = firstMenuItem .locator( '..' ) // parent selector. @@ -671,13 +664,6 @@ test.describe( 'List view editing', () => { hasText: 'Block 1 of 2, Level 1', // proxy for filtering by description. } ); - // Focus the node to reveal the "3 dots" options menu button. - const firstMenuItemAnchor = listView.getByRole( 'link', { - name: 'Top Level Item 1', - includeHidden: true, - } ); - await firstMenuItemAnchor.focus(); - // The options menu button is a sibling of the menu item gridcell. const firstItemOptions = firstMenuItem .locator( '..' ) // parent selector. From 60b78334abf5e3a4d3fa59e697168672afe0dc48 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 30 Mar 2023 11:21:47 +0100 Subject: [PATCH 17/20] Avoid overly complex selectors by targetted Submenu for item removal test --- .../specs/editor/blocks/navigation.spec.js | 31 ++++++------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index d4f96ebdffae00..25bc73fe43a767 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -504,7 +504,7 @@ test.describe( 'List view editing', () => { ).toBeVisible(); } ); - test( `can remove menu items`, async ( { + test.only( `can remove menu items`, async ( { admin, page, editor, @@ -522,33 +522,22 @@ test.describe( 'List view editing', () => { description: 'Structure for navigation menu: Test Menu', } ); - // click on options menu for the first menu item and select remove. - const firstMenuItem = listView - .getByRole( 'gridcell', { - name: 'Page Link link', - } ) - .filter( { - hasText: 'Block 1 of 2, Level 1', // proxy for filtering by description. - } ); - // The options menu button is a sibling of the menu item gridcell. - const firstItemOptions = firstMenuItem - .locator( '..' ) // parent selector. - .getByRole( 'button', { - name: 'Options for Page Link block', - } ); + const submenuOptions = listView.getByRole( 'button', { + name: 'Options for Submenu block', + } ); // Open the options menu. - await firstItemOptions.click(); + await submenuOptions.click(); // usage of `page` is required because the options menu is rendered into a slot // outside of the treegrid. const removeBlockOption = page .getByRole( 'menu', { - name: 'Options for Page Link block', + name: 'Options for Submenu block', } ) .getByRole( 'menuitem', { - name: 'Remove Top Level Item 1', + name: 'Remove Top Level Item 2', } ); await removeBlockOption.click(); @@ -557,12 +546,12 @@ test.describe( 'List view editing', () => { await expect( listView .getByRole( 'gridcell', { - name: 'Page Link link', + name: 'Submenu link', } ) .filter( { - hasText: 'Block 1 of 1, Level 1', // proxy for filtering by description. + hasText: 'Block 2 of 2, Level 1', // proxy for filtering by description. } ) - .getByText( 'Top Level Item 1' ) + .getByText( 'Top Level Item 2' ) ).not.toBeVisible(); } ); From c8d7350b3fda7dc6d1c3d7c3f818b4fedb7d99da Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 30 Mar 2023 11:22:30 +0100 Subject: [PATCH 18/20] Remove comment --- test/e2e/specs/editor/blocks/navigation.spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 25bc73fe43a767..9066650f2c48da 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -522,7 +522,6 @@ test.describe( 'List view editing', () => { description: 'Structure for navigation menu: Test Menu', } ); - // The options menu button is a sibling of the menu item gridcell. const submenuOptions = listView.getByRole( 'button', { name: 'Options for Submenu block', } ); From 5b74e150d41bf37ec429a304ebe735c652fb94e9 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 30 Mar 2023 11:28:40 +0100 Subject: [PATCH 19/20] Test editing a menu item actually updates in the list view --- .../specs/editor/blocks/navigation.spec.js | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 9066650f2c48da..650d1070077fec 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -554,7 +554,7 @@ test.describe( 'List view editing', () => { ).not.toBeVisible(); } ); - test( `can edit menu items`, async ( { + test.only( `can edit menu items`, async ( { admin, page, editor, @@ -609,6 +609,16 @@ test.describe( 'List view editing', () => { } ) ).toBeVisible(); + const labelInput = blockSettings.getByRole( 'textbox', { + name: 'Label', + } ); + + await expect( labelInput ).toHaveValue( 'Top Level Item 1' ); + + await labelInput.focus(); + + await page.keyboard.type( 'Changed label' ); + // Click the back button to go back to the Nav block. await blockSettings .getByRole( 'button', { @@ -622,6 +632,18 @@ test.describe( 'List view editing', () => { } ); await expect( listViewPanel ).toBeVisible(); + + // Check the label was updated. + await expect( + listViewPanel + .getByRole( 'gridcell', { + name: 'Page Link link', + } ) + .filter( { + hasText: 'Block 1 of 2, Level 1', // proxy for filtering by description. + } ) + .getByText( 'Changed label' ) // new label text + ).toBeVisible(); } ); test( `can add submenus`, async ( { From d94e5c1ea2326788d4037e59905e0d569aedd89d Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 30 Mar 2023 11:43:13 +0100 Subject: [PATCH 20/20] Remove .only --- test/e2e/specs/editor/blocks/navigation.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/specs/editor/blocks/navigation.spec.js b/test/e2e/specs/editor/blocks/navigation.spec.js index 650d1070077fec..a42594f3f2dce8 100644 --- a/test/e2e/specs/editor/blocks/navigation.spec.js +++ b/test/e2e/specs/editor/blocks/navigation.spec.js @@ -504,7 +504,7 @@ test.describe( 'List view editing', () => { ).toBeVisible(); } ); - test.only( `can remove menu items`, async ( { + test( `can remove menu items`, async ( { admin, page, editor, @@ -554,7 +554,7 @@ test.describe( 'List view editing', () => { ).not.toBeVisible(); } ); - test.only( `can edit menu items`, async ( { + test( `can edit menu items`, async ( { admin, page, editor,