@wordpress/e2e-tests 2.5.0 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +2 -2
  2. package/config/flaky-tests-reporter.js +94 -0
  3. package/config/setup-test-framework.js +7 -0
  4. package/jest.config.js +11 -1
  5. package/package.json +6 -5
  6. package/plugins/iframed-block/block.json +16 -0
  7. package/plugins/iframed-block/editor.css +6 -0
  8. package/plugins/iframed-block/editor.js +18 -0
  9. package/plugins/iframed-block/jquery.test.js +7 -0
  10. package/plugins/iframed-block/script.js +7 -0
  11. package/plugins/iframed-block/style.css +9 -0
  12. package/plugins/iframed-block.php +46 -0
  13. package/specs/editor/plugins/__snapshots__/iframed-block.test.js.snap +7 -0
  14. package/specs/editor/plugins/align-hook.test.js +116 -105
  15. package/specs/editor/plugins/iframed-block.test.js +58 -0
  16. package/specs/editor/various/__snapshots__/copy-cut-paste-whole-blocks.test.js.snap +28 -0
  17. package/specs/editor/various/__snapshots__/rich-text.test.js.snap +15 -3
  18. package/specs/editor/various/block-grouping.test.js +2 -2
  19. package/specs/editor/various/copy-cut-paste-whole-blocks.test.js +92 -0
  20. package/specs/editor/various/embedding.test.js +1 -1
  21. package/specs/editor/various/inserting-blocks.test.js +23 -0
  22. package/specs/editor/various/rich-text.test.js +29 -1
  23. package/specs/editor/various/writing-flow.test.js +4 -2
  24. package/specs/experiments/__snapshots__/navigation-editor.test.js.snap +27 -33
  25. package/specs/experiments/blocks/__snapshots__/navigation.test.js.snap +29 -19
  26. package/specs/experiments/blocks/navigation.test.js +93 -17
  27. package/specs/experiments/fixtures/menu-items-request-fixture.json +84 -0
  28. package/specs/experiments/navigation-editor.test.js +332 -233
  29. package/specs/experiments/template-revert.test.js +1 -1
  30. package/specs/performance/site-editor.test.js +2 -17
  31. package/specs/widgets/customizing-widgets.test.js +94 -1
  32. package/specs/widgets/editing-widgets.test.js +6 -0
@@ -1,5 +1,19 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
+ exports[`Copy/cut/paste of whole blocks can copy group onto non textual element (image, spacer) 1`] = `""`;
4
+
5
+ exports[`Copy/cut/paste of whole blocks can copy group onto non textual element (image, spacer) 2`] = `
6
+ "<!-- wp:paragraph -->
7
+ <p></p>
8
+ <!-- /wp:paragraph -->
9
+
10
+ <!-- wp:group -->
11
+ <div class=\\"wp-block-group\\"><!-- wp:paragraph -->
12
+ <p>P</p>
13
+ <!-- /wp:paragraph --></div>
14
+ <!-- /wp:group -->"
15
+ `;
16
+
3
17
  exports[`Copy/cut/paste of whole blocks should copy and paste individual blocks 1`] = `
4
18
  "<!-- wp:paragraph -->
5
19
  <p>Here is a unique string so we can test copying.</p>
@@ -56,6 +70,20 @@ exports[`Copy/cut/paste of whole blocks should cut and paste individual blocks 2
56
70
  <!-- /wp:paragraph -->"
57
71
  `;
58
72
 
73
+ exports[`Copy/cut/paste of whole blocks should handle paste events once 1`] = `""`;
74
+
75
+ exports[`Copy/cut/paste of whole blocks should handle paste events once 2`] = `
76
+ "<!-- wp:paragraph -->
77
+ <p></p>
78
+ <!-- /wp:paragraph -->
79
+
80
+ <!-- wp:group -->
81
+ <div class=\\"wp-block-group\\"><!-- wp:paragraph -->
82
+ <p>P</p>
83
+ <!-- /wp:paragraph --></div>
84
+ <!-- /wp:group -->"
85
+ `;
86
+
59
87
  exports[`Copy/cut/paste of whole blocks should respect inline copy in places like input fields and textareas 1`] = `
60
88
  "<!-- wp:shortcode -->
61
89
  [my-shortcode]
@@ -54,6 +54,18 @@ exports[`RichText should navigate arround emoji 1`] = `
54
54
  <!-- /wp:paragraph -->"
55
55
  `;
56
56
 
57
+ exports[`RichText should navigate consecutive format boundaries 1`] = `
58
+ "<!-- wp:paragraph -->
59
+ <p><strong>1</strong><em>2</em></p>
60
+ <!-- /wp:paragraph -->"
61
+ `;
62
+
63
+ exports[`RichText should navigate consecutive format boundaries 2`] = `
64
+ "<!-- wp:paragraph -->
65
+ <p><strong>1</strong>-<em>2</em></p>
66
+ <!-- /wp:paragraph -->"
67
+ `;
68
+
57
69
  exports[`RichText should not format text after code backtick 1`] = `
58
70
  "<!-- wp:paragraph -->
59
71
  <p>A <code>backtick</code> and more.</p>
@@ -90,17 +102,17 @@ exports[`RichText should only mutate text data on input 1`] = `
90
102
 
91
103
  exports[`RichText should preserve internal formatting 1`] = `
92
104
  "<!-- wp:paragraph -->
93
- <p><span class=\\"has-inline-color has-cyan-bluish-gray-color\\">1</span></p>
105
+ <p><mark style=\\"background-color:rgba(0, 0, 0, 0)\\" class=\\"has-inline-color has-cyan-bluish-gray-color\\">1</mark></p>
94
106
  <!-- /wp:paragraph -->"
95
107
  `;
96
108
 
97
109
  exports[`RichText should preserve internal formatting 2`] = `
98
110
  "<!-- wp:paragraph -->
99
- <p><span class=\\"has-inline-color has-cyan-bluish-gray-color\\">1</span></p>
111
+ <p><mark style=\\"background-color:rgba(0, 0, 0, 0)\\" class=\\"has-inline-color has-cyan-bluish-gray-color\\">1</mark></p>
100
112
  <!-- /wp:paragraph -->
101
113
 
102
114
  <!-- wp:paragraph -->
103
- <p><span class=\\"has-inline-color has-cyan-bluish-gray-color\\">1</span></p>
115
+ <p><mark style=\\"background-color:rgba(0, 0, 0, 0)\\" class=\\"has-inline-color has-cyan-bluish-gray-color\\">1</mark></p>
104
116
  <!-- /wp:paragraph -->"
105
117
  `;
106
118
 
@@ -163,7 +163,7 @@ describe( 'Block Grouping', () => {
163
163
  await insertBlock( 'Image' );
164
164
  await clickBlockToolbarButton( 'Align' );
165
165
  const fullButton = await page.waitForXPath(
166
- `//button[contains(@class,'components-dropdown-menu__menu-item') and contains(text(), 'Full width')]`
166
+ `//button[contains(@class,'components-dropdown-menu__menu-item')]//span[contains(text(), 'Full width')]`
167
167
  );
168
168
  await fullButton.evaluate( ( element ) =>
169
169
  element.scrollIntoView()
@@ -174,7 +174,7 @@ describe( 'Block Grouping', () => {
174
174
  await insertBlock( 'Image' );
175
175
  await clickBlockToolbarButton( 'Align' );
176
176
  const wideButton = await page.waitForXPath(
177
- `//button[contains(@class,'components-dropdown-menu__menu-item') and contains(text(), 'Wide width')]`
177
+ `//button[contains(@class,'components-dropdown-menu__menu-item')]//span[contains(text(), 'Wide width')]`
178
178
  );
179
179
  await wideButton.evaluate( ( element ) =>
180
180
  element.scrollIntoView()
@@ -92,4 +92,96 @@ describe( 'Copy/cut/paste of whole blocks', () => {
92
92
  await pressKeyWithModifier( 'primary', 'v' );
93
93
  expect( await getEditedPostContent() ).toMatchSnapshot();
94
94
  } );
95
+
96
+ it( 'should handle paste events once', async () => {
97
+ // Add group block with paragraph
98
+ await insertBlock( 'Group' );
99
+ await page.click( '.block-editor-button-block-appender' );
100
+ await page.click( '.editor-block-list-item-paragraph' );
101
+ await page.keyboard.type( 'P' );
102
+ await page.keyboard.press( 'ArrowLeft' );
103
+ await page.keyboard.press( 'ArrowLeft' );
104
+ // Cut group
105
+ await pressKeyWithModifier( 'primary', 'x' );
106
+ expect( await getEditedPostContent() ).toMatchSnapshot();
107
+
108
+ await page.keyboard.press( 'Enter' );
109
+
110
+ await page.evaluate( () => {
111
+ window.e2eTestPasteOnce = [];
112
+ let oldBlocks = wp.data.select( 'core/block-editor' ).getBlocks();
113
+ wp.data.subscribe( () => {
114
+ const blocks = wp.data
115
+ .select( 'core/block-editor' )
116
+ .getBlocks();
117
+ if ( blocks !== oldBlocks ) {
118
+ window.e2eTestPasteOnce.push(
119
+ blocks.map( ( { clientId, name } ) => ( {
120
+ clientId,
121
+ name,
122
+ } ) )
123
+ );
124
+ }
125
+ oldBlocks = blocks;
126
+ } );
127
+ } );
128
+
129
+ // Paste
130
+ await pressKeyWithModifier( 'primary', 'v' );
131
+
132
+ // Blocks should only be modified once, not twice with new clientIds on a single paste action
133
+ const blocksUpdated = await page.evaluate(
134
+ () => window.e2eTestPasteOnce
135
+ );
136
+
137
+ expect( blocksUpdated.length ).toEqual( 1 );
138
+ expect( await getEditedPostContent() ).toMatchSnapshot();
139
+ } );
140
+
141
+ it( 'can copy group onto non textual element (image, spacer)', async () => {
142
+ // Add group block with paragraph
143
+ await insertBlock( 'Group' );
144
+ await page.click( '.block-editor-button-block-appender' );
145
+ await page.click( '.editor-block-list-item-paragraph' );
146
+ await page.keyboard.type( 'P' );
147
+ await page.keyboard.press( 'ArrowLeft' );
148
+ await page.keyboard.press( 'ArrowLeft' );
149
+ // Cut group
150
+ await pressKeyWithModifier( 'primary', 'x' );
151
+ expect( await getEditedPostContent() ).toMatchSnapshot();
152
+
153
+ await page.keyboard.press( 'Enter' );
154
+
155
+ // Insert a non textual element (a spacer)
156
+ await insertBlock( 'Spacer' );
157
+ // Spacer is focused
158
+ await page.evaluate( () => {
159
+ window.e2eTestPasteOnce = [];
160
+ let oldBlocks = wp.data.select( 'core/block-editor' ).getBlocks();
161
+ wp.data.subscribe( () => {
162
+ const blocks = wp.data
163
+ .select( 'core/block-editor' )
164
+ .getBlocks();
165
+ if ( blocks !== oldBlocks ) {
166
+ window.e2eTestPasteOnce.push(
167
+ blocks.map( ( { clientId, name } ) => ( {
168
+ clientId,
169
+ name,
170
+ } ) )
171
+ );
172
+ }
173
+ oldBlocks = blocks;
174
+ } );
175
+ } );
176
+
177
+ await pressKeyWithModifier( 'primary', 'v' );
178
+
179
+ // Paste should be handled on non-textual elements and only handled once.
180
+ const blocksUpdated = await page.evaluate(
181
+ () => window.e2eTestPasteOnce
182
+ );
183
+
184
+ expect( blocksUpdated.length ).toEqual( 1 );
185
+ expect( await getEditedPostContent() ).toMatchSnapshot();
186
+ } );
95
187
  } );
@@ -17,7 +17,7 @@ import {
17
17
  const MOCK_EMBED_WORDPRESS_SUCCESS_RESPONSE = {
18
18
  url: 'https://wordpress.org/gutenberg/handbook/block-api/attributes/',
19
19
  html:
20
- '<div class="wp-embedded-content" data-secret="shhhh it is a secret">WordPress embed</div>',
20
+ '<div class="wp-embedded-content" data-secret="shhhh it is a secret"></div>',
21
21
  type: 'rich',
22
22
  provider_name: 'WordPress',
23
23
  provider_url: 'https://wordpress.org',
@@ -11,6 +11,7 @@ import {
11
11
  searchForBlock,
12
12
  setBrowserViewport,
13
13
  showBlockToolbar,
14
+ pressKeyWithModifier,
14
15
  } from '@wordpress/e2e-test-utils';
15
16
 
16
17
  /** @typedef {import('puppeteer').ElementHandle} ElementHandle */
@@ -354,6 +355,28 @@ describe( 'Inserting blocks', () => {
354
355
  expect( await getEditedPostContent() ).toMatchSnapshot();
355
356
  } );
356
357
 
358
+ it( 'passes the search value in the main inserter when clicking `Browse all`', async () => {
359
+ const INSERTER_SEARCH_SELECTOR =
360
+ '.block-editor-inserter__search input,.block-editor-inserter__search-input,input.block-editor-inserter__search';
361
+ await insertBlock( 'Group' );
362
+ await insertBlock( 'Paragraph' );
363
+ await page.keyboard.type( 'Text' );
364
+ await page.click( '[data-type="core/group"] [aria-label="Add block"]' );
365
+ await page.waitForSelector( INSERTER_SEARCH_SELECTOR );
366
+ await page.focus( INSERTER_SEARCH_SELECTOR );
367
+ await pressKeyWithModifier( 'primary', 'a' );
368
+ const searchTerm = 'Heading';
369
+ await page.keyboard.type( searchTerm );
370
+ const browseAll = await page.waitForXPath(
371
+ '//button[text()="Browse all"]'
372
+ );
373
+ await browseAll.click();
374
+ const availableBlocks = await page.$$(
375
+ '.block-editor-block-types-list__list-item'
376
+ );
377
+ expect( availableBlocks ).toHaveLength( 1 );
378
+ } );
379
+
357
380
  // Check for regression of https://github.com/WordPress/gutenberg/issues/27586
358
381
  it( 'closes the main inserter after inserting a single-use block, like the More block', async () => {
359
382
  await insertBlock( 'More' );
@@ -385,12 +385,16 @@ describe( 'RichText', () => {
385
385
  await clickBlockToolbarButton( 'More' );
386
386
 
387
387
  const button = await page.waitForXPath(
388
- `//button[contains(text(), 'Text color')]`
388
+ `//button[text()='Highlight']`
389
389
  );
390
390
  // Clicks may fail if the button is out of view. Assure it is before click.
391
391
  await button.evaluate( ( element ) => element.scrollIntoView() );
392
392
  await button.click();
393
393
 
394
+ // Tab to the "Text" tab.
395
+ await page.keyboard.press( 'Tab' );
396
+ // Tab to black.
397
+ await page.keyboard.press( 'Tab' );
394
398
  // Select color other than black.
395
399
  await page.keyboard.press( 'Tab' );
396
400
  await page.keyboard.press( 'Enter' );
@@ -470,4 +474,28 @@ describe( 'RichText', () => {
470
474
 
471
475
  expect( await getEditedPostContent() ).toMatchSnapshot();
472
476
  } );
477
+
478
+ it( 'should navigate consecutive format boundaries', async () => {
479
+ await clickBlockAppender();
480
+ await pressKeyWithModifier( 'primary', 'b' );
481
+ await page.keyboard.type( '1' );
482
+ await pressKeyWithModifier( 'primary', 'b' );
483
+ await pressKeyWithModifier( 'primary', 'i' );
484
+ await page.keyboard.type( '2' );
485
+ await pressKeyWithModifier( 'primary', 'i' );
486
+
487
+ expect( await getEditedPostContent() ).toMatchSnapshot();
488
+
489
+ // Should move into the second format.
490
+ await page.keyboard.press( 'ArrowLeft' );
491
+ // Should move to the start of the second format.
492
+ await page.keyboard.press( 'ArrowLeft' );
493
+ // Should move between the first and second format.
494
+ await page.keyboard.press( 'ArrowLeft' );
495
+
496
+ await page.keyboard.type( '-' );
497
+
498
+ // Expect: <strong>1</strong>-<em>2</em>
499
+ expect( await getEditedPostContent() ).toMatchSnapshot();
500
+ } );
473
501
  } );
@@ -9,7 +9,6 @@ import {
9
9
  pressKeyWithModifier,
10
10
  insertBlock,
11
11
  clickBlockToolbarButton,
12
- clickButton,
13
12
  } from '@wordpress/e2e-test-utils';
14
13
 
15
14
  const getActiveBlockName = async () =>
@@ -556,7 +555,10 @@ describe( 'Writing Flow', () => {
556
555
  await page.keyboard.type( '/image' );
557
556
  await page.keyboard.press( 'Enter' );
558
557
  await clickBlockToolbarButton( 'Align' );
559
- await clickButton( 'Wide width' );
558
+ const wideButton = await page.waitForXPath(
559
+ `//button[contains(@class,'components-dropdown-menu__menu-item')]//span[contains(text(), 'Wide width')]`
560
+ );
561
+ await wideButton.click();
560
562
 
561
563
  // Select the previous block.
562
564
  await page.keyboard.press( 'ArrowUp' );
@@ -4,42 +4,36 @@ exports[`Navigation editor allows creation of a menu when there are existing men
4
4
 
5
5
  exports[`Navigation editor allows creation of a menu when there are no current menu items 1`] = `
6
6
  "<!-- wp:navigation {\\"orientation\\":\\"vertical\\"} -->
7
- <!-- wp:navigation-link {\\"label\\":\\"My page\\",\\"type\\":\\"page\\",\\"id\\":1,\\"url\\":\\"https://example.com/1\\",\\"isTopLevelLink\\":true} /-->
7
+ <!-- wp:navigation-link {\\"label\\":\\"My page\\",\\"type\\":\\"page\\",\\"id\\":\\"number\\",\\"url\\":\\"string\\",\\"isTopLevelLink\\":true} /-->
8
8
  <!-- /wp:navigation -->"
9
9
  `;
10
10
 
11
- exports[`Navigation editor displays the first menu from the REST response when at least one menu exists 1`] = `
11
+ exports[`Navigation editor displays the first created menu when at least one menu exists 1`] = `
12
12
  "<!-- wp:navigation {\\"orientation\\":\\"vertical\\"} -->
13
- <!-- wp:navigation-link {\\"label\\":\\"Home\\",\\"type\\":\\"custom\\",\\"url\\":\\"http://localhost:8889/\\",\\"kind\\":\\"custom\\",\\"isTopLevelLink\\":true} /-->
14
-
15
- <!-- wp:navigation-link {\\"label\\":\\"Accusamus quo repellat illum magnam quas\\",\\"type\\":\\"page\\",\\"id\\":41,\\"url\\":\\"http://localhost:8889/?page_id=41\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":true} -->
16
- <!-- wp:navigation-link {\\"label\\":\\"Debitis cum consequatur sit doloremque\\",\\"type\\":\\"page\\",\\"id\\":51,\\"url\\":\\"http://localhost:8889/?page_id=51\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} /-->
17
- <!-- /wp:navigation-link -->
18
-
19
- <!-- wp:navigation-link {\\"label\\":\\"Est ea vero non nihil officiis in\\",\\"type\\":\\"page\\",\\"id\\":53,\\"url\\":\\"http://localhost:8889/?page_id=53\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":true} -->
20
- <!-- wp:navigation-link {\\"label\\":\\"Fuga odio quis tempora\\",\\"type\\":\\"page\\",\\"id\\":56,\\"url\\":\\"http://localhost:8889/?page_id=56\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} -->
21
- <!-- wp:navigation-link {\\"label\\":\\"In consectetur repellendus eveniet maiores aperiam\\",\\"type\\":\\"page\\",\\"id\\":15,\\"url\\":\\"http://localhost:8889/?page_id=15\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} -->
22
- <!-- wp:navigation-link {\\"label\\":\\"Mollitia maiores consequatur ea dolorem blanditiis\\",\\"type\\":\\"page\\",\\"id\\":45,\\"url\\":\\"http://localhost:8889/?page_id=45\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} -->
23
- <!-- wp:navigation-link {\\"label\\":\\"Necessitatibus nisi qui qui necessitatibus quaerat possimus\\",\\"type\\":\\"page\\",\\"id\\":27,\\"url\\":\\"http://localhost:8889/?page_id=27\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} /-->
24
- <!-- /wp:navigation-link -->
25
- <!-- /wp:navigation-link -->
26
- <!-- /wp:navigation-link -->
27
- <!-- /wp:navigation-link -->
28
-
29
- <!-- wp:navigation-link {\\"label\\":\\"Nulla omnis autem dolores eligendi\\",\\"type\\":\\"page\\",\\"id\\":43,\\"url\\":\\"http://localhost:8889/?page_id=43\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":true} /-->
30
-
31
- <!-- wp:navigation-link {\\"label\\":\\"Sample Page\\",\\"type\\":\\"page\\",\\"id\\":2,\\"url\\":\\"http://localhost:8889/?page_id=2\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":true} /-->
32
-
33
- <!-- wp:navigation-link {\\"label\\":\\"Beatae qui labore voluptas eveniet officia quia voluptas qui porro sequi et aut est\\",\\"type\\":\\"category\\",\\"description\\":\\"Ratione nemo ut aut ullam sed assumenda quis est exercitationem\\",\\"id\\":7,\\"url\\":\\"http://localhost:8889/?cat=7\\",\\"kind\\":\\"taxonomy\\",\\"isTopLevelLink\\":true} -->
34
- <!-- wp:navigation-link {\\"label\\":\\"Et minus itaque velit tempore hic quisquam saepe quas asperiores\\",\\"type\\":\\"category\\",\\"description\\":\\"Vel fuga enim rerum perspiciatis sapiente mollitia magni ut molestiae labore quae quia quia libero perspiciatis voluptatem quidem deleniti eveniet laboriosam doloribus dolor laborum accusantium modi ducimus itaque rerum cum nostrum\\",\\"id\\":19,\\"url\\":\\"http://localhost:8889/?cat=19\\",\\"kind\\":\\"taxonomy\\",\\"isTopLevelLink\\":false} -->
35
- <!-- wp:navigation-link {\\"label\\":\\"Et quas a et mollitia et voluptas optio voluptate quia quo unde aut in nostrum iste impedit quisquam id aut\\",\\"type\\":\\"category\\",\\"description\\":\\"Quas sit labore earum omnis eos sint iste est possimus harum aut soluta sint optio quos distinctio inventore voluptate non ut aliquam ad ut voluptates fugiat numquam magnam modi repellendus modi laudantium et debitis officia est voluptatum quidem unde molestiae animi vero fuga accusamus nam\\",\\"id\\":6,\\"url\\":\\"http://localhost:8889/?cat=6\\",\\"kind\\":\\"taxonomy\\",\\"isTopLevelLink\\":false} -->
36
- <!-- wp:navigation-link {\\"label\\":\\"Illo quis sit impedit itaque expedita earum deserunt magni doloremque velit eum id error\\",\\"type\\":\\"category\\",\\"description\\":\\"Doloremque vero sunt officiis iste voluptatibus voluptas molestiae sint asperiores recusandae amet praesentium et explicabo nesciunt similique voluptatum laudantium amet officiis quas distinctio quis enim nihil tempora\\",\\"id\\":16,\\"url\\":\\"http://localhost:8889/?cat=16\\",\\"kind\\":\\"taxonomy\\",\\"isTopLevelLink\\":false} /-->
37
- <!-- /wp:navigation-link -->
38
- <!-- /wp:navigation-link -->
39
- <!-- /wp:navigation-link -->
40
-
41
- <!-- wp:navigation-link {\\"label\\":\\"WordPress.org\\",\\"type\\":\\"custom\\",\\"url\\":\\"https://wordpress.org\\",\\"kind\\":\\"custom\\",\\"isTopLevelLink\\":true} -->
42
- <!-- wp:navigation-link {\\"label\\":\\"Google\\",\\"type\\":\\"custom\\",\\"url\\":\\"https://google.com\\",\\"kind\\":\\"custom\\",\\"isTopLevelLink\\":false} /-->
43
- <!-- /wp:navigation-link -->
13
+ <!-- wp:navigation-link {\\"label\\":\\"Home\\",\\"type\\":\\"custom\\",\\"url\\":\\"string\\",\\"kind\\":\\"custom\\",\\"isTopLevelLink\\":true} /-->
14
+
15
+ <!-- wp:navigation-submenu {\\"label\\":\\"About\\",\\"type\\":\\"page\\",\\"id\\":\\"number\\",\\"url\\":\\"string\\",\\"kind\\":\\"post-type\\",\\"isTopLevelItem\\":true} -->
16
+ <!-- wp:navigation-link {\\"label\\":\\"Our team\\",\\"type\\":\\"page\\",\\"id\\":\\"number\\",\\"url\\":\\"string\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} /-->
17
+ <!-- /wp:navigation-submenu -->
18
+
19
+ <!-- wp:navigation-submenu {\\"label\\":\\"Shop\\",\\"type\\":\\"page\\",\\"id\\":\\"number\\",\\"url\\":\\"string\\",\\"kind\\":\\"post-type\\",\\"isTopLevelItem\\":true} -->
20
+ <!-- wp:navigation-submenu {\\"label\\":\\"Winter apparel\\",\\"type\\":\\"page\\",\\"id\\":\\"number\\",\\"url\\":\\"string\\",\\"kind\\":\\"post-type\\",\\"isTopLevelItem\\":false} -->
21
+ <!-- wp:navigation-link {\\"label\\":\\"Chunky socks\\",\\"type\\":\\"page\\",\\"id\\":\\"number\\",\\"url\\":\\"string\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} /-->
22
+
23
+ <!-- wp:navigation-link {\\"label\\":\\"Hideous hats\\",\\"type\\":\\"page\\",\\"id\\":\\"number\\",\\"url\\":\\"string\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} /-->
24
+
25
+ <!-- wp:navigation-link {\\"label\\":\\"Glorious gloves\\",\\"type\\":\\"page\\",\\"id\\":\\"number\\",\\"url\\":\\"string\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} /-->
26
+
27
+ <!-- wp:navigation-link {\\"label\\":\\"Jazzy Jumpers\\",\\"type\\":\\"page\\",\\"id\\":\\"number\\",\\"url\\":\\"string\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} /-->
28
+ <!-- /wp:navigation-submenu -->
29
+ <!-- /wp:navigation-submenu -->
30
+
31
+ <!-- wp:navigation-link {\\"label\\":\\"Shipping\\",\\"type\\":\\"page\\",\\"id\\":\\"number\\",\\"url\\":\\"string\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":true} /-->
32
+
33
+ <!-- wp:navigation-link {\\"label\\":\\"Contact Us\\",\\"type\\":\\"page\\",\\"id\\":\\"number\\",\\"url\\":\\"string\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":true} /-->
34
+
35
+ <!-- wp:navigation-submenu {\\"label\\":\\"WordPress.org\\",\\"type\\":\\"custom\\",\\"url\\":\\"string\\",\\"kind\\":\\"custom\\",\\"isTopLevelItem\\":true} -->
36
+ <!-- wp:navigation-link {\\"label\\":\\"Google\\",\\"type\\":\\"custom\\",\\"url\\":\\"string\\",\\"kind\\":\\"custom\\",\\"isTopLevelLink\\":false} /-->
37
+ <!-- /wp:navigation-submenu -->
44
38
  <!-- /wp:navigation -->"
45
39
  `;
@@ -4,35 +4,35 @@ exports[`Navigation Creating from existing Menus allows a navigation block to be
4
4
  "<!-- wp:navigation -->
5
5
  <!-- wp:navigation-link {\\"label\\":\\"Home\\",\\"type\\":\\"custom\\",\\"url\\":\\"http://localhost:8889/\\",\\"kind\\":\\"custom\\",\\"isTopLevelLink\\":true} /-->
6
6
 
7
- <!-- wp:navigation-link {\\"label\\":\\"Accusamus quo repellat illum magnam quas\\",\\"type\\":\\"page\\",\\"id\\":41,\\"url\\":\\"http://localhost:8889/?page_id=41\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":true} -->
7
+ <!-- wp:navigation-submenu {\\"label\\":\\"Accusamus quo repellat illum magnam quas\\",\\"type\\":\\"page\\",\\"id\\":41,\\"url\\":\\"http://localhost:8889/?page_id=41\\",\\"kind\\":\\"post-type\\",\\"isTopLevelItem\\":true} -->
8
8
  <!-- wp:navigation-link {\\"label\\":\\"Debitis cum consequatur sit doloremque\\",\\"type\\":\\"page\\",\\"id\\":51,\\"url\\":\\"http://localhost:8889/?page_id=51\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} /-->
9
- <!-- /wp:navigation-link -->
9
+ <!-- /wp:navigation-submenu -->
10
10
 
11
- <!-- wp:navigation-link {\\"label\\":\\"Est ea vero non nihil officiis in\\",\\"type\\":\\"page\\",\\"id\\":53,\\"url\\":\\"http://localhost:8889/?page_id=53\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":true} -->
12
- <!-- wp:navigation-link {\\"label\\":\\"Fuga odio quis tempora\\",\\"type\\":\\"page\\",\\"id\\":56,\\"url\\":\\"http://localhost:8889/?page_id=56\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} -->
13
- <!-- wp:navigation-link {\\"label\\":\\"In consectetur repellendus eveniet maiores aperiam\\",\\"type\\":\\"page\\",\\"id\\":15,\\"url\\":\\"http://localhost:8889/?page_id=15\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} -->
14
- <!-- wp:navigation-link {\\"label\\":\\"Mollitia maiores consequatur ea dolorem blanditiis\\",\\"type\\":\\"page\\",\\"id\\":45,\\"url\\":\\"http://localhost:8889/?page_id=45\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} -->
11
+ <!-- wp:navigation-submenu {\\"label\\":\\"Est ea vero non nihil officiis in\\",\\"type\\":\\"page\\",\\"id\\":53,\\"url\\":\\"http://localhost:8889/?page_id=53\\",\\"kind\\":\\"post-type\\",\\"isTopLevelItem\\":true} -->
12
+ <!-- wp:navigation-submenu {\\"label\\":\\"Fuga odio quis tempora\\",\\"type\\":\\"page\\",\\"id\\":56,\\"url\\":\\"http://localhost:8889/?page_id=56\\",\\"kind\\":\\"post-type\\",\\"isTopLevelItem\\":false} -->
13
+ <!-- wp:navigation-submenu {\\"label\\":\\"In consectetur repellendus eveniet maiores aperiam\\",\\"type\\":\\"page\\",\\"id\\":15,\\"url\\":\\"http://localhost:8889/?page_id=15\\",\\"kind\\":\\"post-type\\",\\"isTopLevelItem\\":false} -->
14
+ <!-- wp:navigation-submenu {\\"label\\":\\"Mollitia maiores consequatur ea dolorem blanditiis\\",\\"type\\":\\"page\\",\\"id\\":45,\\"url\\":\\"http://localhost:8889/?page_id=45\\",\\"kind\\":\\"post-type\\",\\"isTopLevelItem\\":false} -->
15
15
  <!-- wp:navigation-link {\\"label\\":\\"Necessitatibus nisi qui qui necessitatibus quaerat possimus\\",\\"type\\":\\"page\\",\\"id\\":27,\\"url\\":\\"http://localhost:8889/?page_id=27\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":false} /-->
16
- <!-- /wp:navigation-link -->
17
- <!-- /wp:navigation-link -->
18
- <!-- /wp:navigation-link -->
19
- <!-- /wp:navigation-link -->
16
+ <!-- /wp:navigation-submenu -->
17
+ <!-- /wp:navigation-submenu -->
18
+ <!-- /wp:navigation-submenu -->
19
+ <!-- /wp:navigation-submenu -->
20
20
 
21
21
  <!-- wp:navigation-link {\\"label\\":\\"Nulla omnis autem dolores eligendi\\",\\"type\\":\\"page\\",\\"id\\":43,\\"url\\":\\"http://localhost:8889/?page_id=43\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":true} /-->
22
22
 
23
23
  <!-- wp:navigation-link {\\"label\\":\\"Sample Page\\",\\"type\\":\\"page\\",\\"id\\":2,\\"url\\":\\"http://localhost:8889/?page_id=2\\",\\"kind\\":\\"post-type\\",\\"isTopLevelLink\\":true} /-->
24
24
 
25
- <!-- wp:navigation-link {\\"label\\":\\"Beatae qui labore voluptas eveniet officia quia voluptas qui porro sequi et aut est\\",\\"type\\":\\"category\\",\\"description\\":\\"Ratione nemo ut aut ullam sed assumenda quis est exercitationem\\",\\"id\\":7,\\"url\\":\\"http://localhost:8889/?cat=7\\",\\"kind\\":\\"taxonomy\\",\\"isTopLevelLink\\":true} -->
26
- <!-- wp:navigation-link {\\"label\\":\\"Et minus itaque velit tempore hic quisquam saepe quas asperiores\\",\\"type\\":\\"category\\",\\"description\\":\\"Vel fuga enim rerum perspiciatis sapiente mollitia magni ut molestiae labore quae quia quia libero perspiciatis voluptatem quidem deleniti eveniet laboriosam doloribus dolor laborum accusantium modi ducimus itaque rerum cum nostrum\\",\\"id\\":19,\\"url\\":\\"http://localhost:8889/?cat=19\\",\\"kind\\":\\"taxonomy\\",\\"isTopLevelLink\\":false} -->
27
- <!-- wp:navigation-link {\\"label\\":\\"Et quas a et mollitia et voluptas optio voluptate quia quo unde aut in nostrum iste impedit quisquam id aut\\",\\"type\\":\\"category\\",\\"description\\":\\"Quas sit labore earum omnis eos sint iste est possimus harum aut soluta sint optio quos distinctio inventore voluptate non ut aliquam ad ut voluptates fugiat numquam magnam modi repellendus modi laudantium et debitis officia est voluptatum quidem unde molestiae animi vero fuga accusamus nam\\",\\"id\\":6,\\"url\\":\\"http://localhost:8889/?cat=6\\",\\"kind\\":\\"taxonomy\\",\\"isTopLevelLink\\":false} -->
25
+ <!-- wp:navigation-submenu {\\"label\\":\\"Beatae qui labore voluptas eveniet officia quia voluptas qui porro sequi et aut est\\",\\"type\\":\\"category\\",\\"description\\":\\"Ratione nemo ut aut ullam sed assumenda quis est exercitationem\\",\\"id\\":7,\\"url\\":\\"http://localhost:8889/?cat=7\\",\\"kind\\":\\"taxonomy\\",\\"isTopLevelItem\\":true} -->
26
+ <!-- wp:navigation-submenu {\\"label\\":\\"Et minus itaque velit tempore hic quisquam saepe quas asperiores\\",\\"type\\":\\"category\\",\\"description\\":\\"Vel fuga enim rerum perspiciatis sapiente mollitia magni ut molestiae labore quae quia quia libero perspiciatis voluptatem quidem deleniti eveniet laboriosam doloribus dolor laborum accusantium modi ducimus itaque rerum cum nostrum\\",\\"id\\":19,\\"url\\":\\"http://localhost:8889/?cat=19\\",\\"kind\\":\\"taxonomy\\",\\"isTopLevelItem\\":false} -->
27
+ <!-- wp:navigation-submenu {\\"label\\":\\"Et quas a et mollitia et voluptas optio voluptate quia quo unde aut in nostrum iste impedit quisquam id aut\\",\\"type\\":\\"category\\",\\"description\\":\\"Quas sit labore earum omnis eos sint iste est possimus harum aut soluta sint optio quos distinctio inventore voluptate non ut aliquam ad ut voluptates fugiat numquam magnam modi repellendus modi laudantium et debitis officia est voluptatum quidem unde molestiae animi vero fuga accusamus nam\\",\\"id\\":6,\\"url\\":\\"http://localhost:8889/?cat=6\\",\\"kind\\":\\"taxonomy\\",\\"isTopLevelItem\\":false} -->
28
28
  <!-- wp:navigation-link {\\"label\\":\\"Illo quis sit impedit itaque expedita earum deserunt magni doloremque velit eum id error\\",\\"type\\":\\"category\\",\\"description\\":\\"Doloremque vero sunt officiis iste voluptatibus voluptas molestiae sint asperiores recusandae amet praesentium et explicabo nesciunt similique voluptatum laudantium amet officiis quas distinctio quis enim nihil tempora\\",\\"id\\":16,\\"url\\":\\"http://localhost:8889/?cat=16\\",\\"kind\\":\\"taxonomy\\",\\"isTopLevelLink\\":false} /-->
29
- <!-- /wp:navigation-link -->
30
- <!-- /wp:navigation-link -->
31
- <!-- /wp:navigation-link -->
29
+ <!-- /wp:navigation-submenu -->
30
+ <!-- /wp:navigation-submenu -->
31
+ <!-- /wp:navigation-submenu -->
32
32
 
33
- <!-- wp:navigation-link {\\"label\\":\\"WordPress.org\\",\\"type\\":\\"custom\\",\\"url\\":\\"https://wordpress.org\\",\\"kind\\":\\"custom\\",\\"isTopLevelLink\\":true} -->
33
+ <!-- wp:navigation-submenu {\\"label\\":\\"WordPress.org\\",\\"type\\":\\"custom\\",\\"url\\":\\"https://wordpress.org\\",\\"kind\\":\\"custom\\",\\"isTopLevelItem\\":true} -->
34
34
  <!-- wp:navigation-link {\\"label\\":\\"Google\\",\\"type\\":\\"custom\\",\\"url\\":\\"https://google.com\\",\\"kind\\":\\"custom\\",\\"isTopLevelLink\\":false} /-->
35
- <!-- /wp:navigation-link -->
35
+ <!-- /wp:navigation-submenu -->
36
36
  <!-- /wp:navigation -->"
37
37
  `;
38
38
 
@@ -40,7 +40,17 @@ exports[`Navigation Creating from existing Menus creates an empty navigation blo
40
40
 
41
41
  exports[`Navigation Creating from existing Pages allows a navigation block to be created using existing pages 1`] = `
42
42
  "<!-- wp:navigation -->
43
- <!-- wp:page-list {\\"isNavigationChild\\":true} /-->
43
+ <!-- wp:page-list {\\"isNavigationChild\\":true,\\"showSubmenuIcon\\":true,\\"openSubmenusOnClick\\":false} /-->
44
+ <!-- /wp:navigation -->"
45
+ `;
46
+
47
+ exports[`Navigation Shows the quick inserter when the block contains non-navigation specific blocks 1`] = `
48
+ "<!-- wp:navigation -->
49
+ <!-- wp:navigation-link {\\"label\\":\\"WP\\",\\"url\\":\\"https://wordpress.org\\",\\"kind\\":\\"custom\\",\\"isTopLevelLink\\":true} /-->
50
+
51
+ <!-- wp:site-title /-->
52
+
53
+ <!-- wp:navigation-link {\\"label\\":\\"WP News\\",\\"url\\":\\"https://wordpress.org/news/\\",\\"kind\\":\\"custom\\",\\"isTopLevelLink\\":true} /-->
44
54
  <!-- /wp:navigation -->"
45
55
  `;
46
56
 
@@ -246,17 +246,6 @@ async function createEmptyNavBlock() {
246
246
  await startEmptyButton.click();
247
247
  }
248
248
 
249
- async function addLinkBlock() {
250
- // Using 'click' here checks for regressions of https://github.com/WordPress/gutenberg/issues/18329,
251
- // an issue where the block appender requires two clicks.
252
- await page.click( '.wp-block-navigation .block-list-appender' );
253
-
254
- const [ linkButton ] = await page.$x(
255
- "//*[contains(@class, 'block-editor-inserter__quick-inserter')]//*[text()='Custom Link']"
256
- );
257
- await linkButton.click();
258
- }
259
-
260
249
  async function toggleSidebar() {
261
250
  await page.click(
262
251
  '.edit-post-header__settings button[aria-label="Settings"]'
@@ -346,7 +335,7 @@ describe( 'Navigation', () => {
346
335
  // Scope element selector to the Editor's "Content" region as otherwise it picks up on
347
336
  // block previews.
348
337
  const navLinkSelector =
349
- '[aria-label="Editor content"][role="region"] div[aria-label="Block: Custom Link"]';
338
+ '[aria-label="Editor content"][role="region"] .wp-block-navigation-item';
350
339
 
351
340
  await page.waitForSelector( navLinkSelector );
352
341
 
@@ -414,7 +403,7 @@ describe( 'Navigation', () => {
414
403
 
415
404
  await createEmptyNavBlock();
416
405
 
417
- await addLinkBlock();
406
+ await page.click( '.wp-block-navigation .block-list-appender' );
418
407
 
419
408
  // Add a link to the Link block.
420
409
  await updateActiveNavigationLink( {
@@ -425,7 +414,7 @@ describe( 'Navigation', () => {
425
414
 
426
415
  await showBlockToolbar();
427
416
 
428
- await addLinkBlock();
417
+ await page.click( '.wp-block-navigation .block-list-appender' );
429
418
 
430
419
  // After adding a new block, search input should be shown immediately.
431
420
  // Verify that Escape would close the popover.
@@ -477,7 +466,7 @@ describe( 'Navigation', () => {
477
466
 
478
467
  await createEmptyNavBlock();
479
468
 
480
- await addLinkBlock();
469
+ await page.click( '.wp-block-navigation .block-list-appender' );
481
470
 
482
471
  // Add a link to the Link block.
483
472
  await updateActiveNavigationLink( {
@@ -487,7 +476,7 @@ describe( 'Navigation', () => {
487
476
 
488
477
  await showBlockToolbar();
489
478
 
490
- await addLinkBlock();
479
+ await page.click( '.wp-block-navigation .block-list-appender' );
491
480
 
492
481
  // Wait for URL input to be focused
493
482
  await page.waitForSelector(
@@ -548,7 +537,7 @@ describe( 'Navigation', () => {
548
537
  // Create an empty nav block.
549
538
  await createEmptyNavBlock();
550
539
 
551
- await addLinkBlock();
540
+ await page.click( '.wp-block-navigation .block-list-appender' );
552
541
 
553
542
  // Wait for URL input to be focused
554
543
  await page.waitForSelector(
@@ -595,6 +584,93 @@ describe( 'Navigation', () => {
595
584
  expect( await getEditedPostContent() ).toMatchSnapshot();
596
585
  } );
597
586
 
587
+ it( 'allows navigation submenus to open on click instead of hover', async () => {
588
+ await mockAllMenusResponses();
589
+
590
+ // Add the navigation block.
591
+ await insertBlock( 'Navigation' );
592
+
593
+ await selectDropDownOption( 'Test Menu 2' );
594
+
595
+ // const blocks = await getAllBlocks();
596
+ // await selectBlockByClientId( blocks[ 0 ].clientId );
597
+
598
+ await toggleSidebar();
599
+
600
+ const [ openOnClickButton ] = await page.$x(
601
+ '//label[contains(text(),"Open submenus on click")]'
602
+ );
603
+
604
+ await openOnClickButton.click();
605
+
606
+ await saveDraft();
607
+
608
+ // Scope element selector to the Editor's "Content" region as otherwise it picks up on
609
+ // block previews.
610
+ const navSubmenuSelector =
611
+ '[aria-label="Editor content"][role="region"] [aria-label="Block: Submenu"]';
612
+
613
+ await page.waitForSelector( navSubmenuSelector );
614
+
615
+ const navSubmenusLength = await page.$$eval(
616
+ navSubmenuSelector,
617
+ ( els ) => els.length
618
+ );
619
+
620
+ const navButtonTogglesSelector =
621
+ '[aria-label="Editor content"][role="region"] [aria-label="Block: Submenu"] button.wp-block-navigation-item__content';
622
+
623
+ await page.waitForSelector( navButtonTogglesSelector );
624
+
625
+ const navButtonTogglesLength = await page.$$eval(
626
+ navButtonTogglesSelector,
627
+ ( els ) => els.length
628
+ );
629
+
630
+ // Assert the correct number of button toggles are present.
631
+ expect( navSubmenusLength ).toEqual( navButtonTogglesLength );
632
+ } );
633
+
634
+ it( 'Shows the quick inserter when the block contains non-navigation specific blocks', async () => {
635
+ // Add the navigation block.
636
+ await insertBlock( 'Navigation' );
637
+
638
+ // Create an empty nav block.
639
+ await page.waitForSelector( '.wp-block-navigation-placeholder' );
640
+
641
+ await createEmptyNavBlock();
642
+
643
+ // Add a Link block first.
644
+ await page.click( '.wp-block-navigation .block-list-appender' );
645
+
646
+ // Add a link to the Link block.
647
+ await updateActiveNavigationLink( {
648
+ url: 'https://wordpress.org',
649
+ label: 'WP',
650
+ type: 'url',
651
+ } );
652
+
653
+ // Now add a different block type.
654
+ await insertBlock( 'Site Title' );
655
+
656
+ // Now try inserting another Link block via the quick inserter.
657
+ await page.click( '.wp-block-navigation .block-list-appender' );
658
+
659
+ const linkButton = await page.waitForSelector(
660
+ '.block-editor-inserter__quick-inserter .editor-block-list-item-navigation-link'
661
+ );
662
+ await linkButton.click();
663
+
664
+ await updateActiveNavigationLink( {
665
+ url: 'https://wordpress.org/news/',
666
+ label: 'WP News',
667
+ type: 'url',
668
+ } );
669
+
670
+ // Expect a Navigation block with two links and a Site Title.
671
+ expect( await getEditedPostContent() ).toMatchSnapshot();
672
+ } );
673
+
598
674
  // The following tests are unstable, roughly around when https://github.com/WordPress/wordpress-develop/pull/1412
599
675
  // landed. The block manually tests well, so let's skip to unblock other PRs and immediately follow up. cc @vcanales
600
676
  it.skip( 'loads frontend code only if the block is present', async () => {