@wordpress/e2e-tests 6.2.0 → 6.3.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.
@@ -1,850 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- // eslint-disable-next-line no-restricted-imports
5
- import { find, findAll } from 'puppeteer-testing-library';
6
-
7
- /**
8
- * WordPress dependencies
9
- */
10
- import {
11
- createJSONResponse,
12
- createMenu,
13
- deleteAllMenus,
14
- pressKeyTimes,
15
- pressKeyWithModifier,
16
- setBrowserViewport,
17
- setUpResponseMocking,
18
- visitAdminPage,
19
- __experimentalRest as rest,
20
- } from '@wordpress/e2e-test-utils';
21
- import { addQueryArgs } from '@wordpress/url';
22
-
23
- /**
24
- * Internal dependencies
25
- */
26
- import { useExperimentalFeatures } from './experimental-features';
27
- import menuItemsFixture from './fixtures/menu-items-request-fixture.json';
28
-
29
- const TYPE_NAMES = {
30
- post: 'post',
31
- page: 'page',
32
- post_tag: 'tag',
33
- category: 'category',
34
- };
35
-
36
- const searchFixture = [
37
- {
38
- id: 300,
39
- title: 'Home',
40
- url: 'https://example.com/home',
41
- type: 'post',
42
- subtype: 'page',
43
- },
44
- {
45
- id: 301,
46
- title: 'About',
47
- url: 'https://example.com/about',
48
- type: 'post',
49
- subtype: 'page',
50
- },
51
- {
52
- id: 302,
53
- title: 'Boats',
54
- url: 'https://example.com/?cat=123',
55
- type: 'category',
56
- },
57
- {
58
- id: 303,
59
- title: 'Faves',
60
- url: 'https://example.com/?tag=456',
61
- type: 'post_tag',
62
- },
63
- ];
64
-
65
- // Matching against variations of the same URL encoded and non-encoded
66
- // produces the most reliable mocking.
67
- const REST_SEARCH_ROUTES = [
68
- '/wp/v2/search',
69
- `rest_route=${ encodeURIComponent( '/wp/v2/search' ) }`,
70
- ];
71
-
72
- const REST_PAGES_ROUTES = [
73
- '/wp/v2/pages',
74
- `rest_route=${ encodeURIComponent( '/wp/v2/pages' ) }`,
75
- ];
76
-
77
- /**
78
- * Determines if a given URL matches any of a given collection of
79
- * routes (expressed as substrings).
80
- *
81
- * @param {string} reqUrl the full URL to be tested for matches.
82
- * @param {Array} routes array of strings to match against the URL.
83
- */
84
- function matchUrlToRoute( reqUrl, routes ) {
85
- return routes.some( ( route ) => reqUrl.includes( route ) );
86
- }
87
-
88
- function getEndpointMocks( matchingRoutes, responsesByMethod ) {
89
- return [ 'GET', 'POST', 'DELETE', 'PUT' ].reduce( ( mocks, restMethod ) => {
90
- if ( responsesByMethod[ restMethod ] ) {
91
- return [
92
- ...mocks,
93
- {
94
- match: ( request ) =>
95
- matchUrlToRoute( request.url(), matchingRoutes ) &&
96
- request.method() === restMethod,
97
- onRequestMatch: createJSONResponse(
98
- responsesByMethod[ restMethod ]
99
- ),
100
- },
101
- ];
102
- }
103
-
104
- return mocks;
105
- }, [] );
106
- }
107
-
108
- function getSearchMocks( responsesByMethod ) {
109
- return getEndpointMocks( REST_SEARCH_ROUTES, responsesByMethod );
110
- }
111
-
112
- function getPagesMocks( responsesByMethod ) {
113
- return getEndpointMocks( REST_PAGES_ROUTES, responsesByMethod );
114
- }
115
-
116
- async function visitNavigationEditor() {
117
- const query = addQueryArgs( '', {
118
- page: 'gutenberg-navigation',
119
- } );
120
- await visitAdminPage( '/admin.php', query );
121
- }
122
-
123
- /**
124
- * Get a list of the editor's current blocks for use in a snapshot.
125
- *
126
- * @return {string} Block HTML.
127
- */
128
- async function getSerializedBlocks() {
129
- const blocks = await page.evaluate( () =>
130
- wp.data.select( 'core/block-editor' ).getBlocks()
131
- );
132
- const safeBlocks = replaceUnstableBlockAttributes( blocks );
133
- return page.evaluate(
134
- ( blocksToSerialize ) => wp.blocks.serialize( blocksToSerialize ),
135
- safeBlocks
136
- );
137
- }
138
-
139
- /**
140
- * Some block attributes contain values that are not stable from test run to
141
- * test run and can't be compared with a snapshot. These are typically the
142
- * ids of posts or pages that are created prior to each test run. Replace those
143
- * values with their types before serializing to a snapshot.
144
- *
145
- * @param {Array} blocks The array of block data.
146
- *
147
- * @return {Array} Updated array of block data.
148
- */
149
- function replaceUnstableBlockAttributes( blocks ) {
150
- return blocks?.map( ( block ) => {
151
- const id = block.attributes.id ? typeof block.attributes.id : undefined;
152
- const url = block.attributes.url
153
- ? typeof block.attributes.url
154
- : undefined;
155
-
156
- return {
157
- ...block,
158
- attributes: {
159
- ...block.attributes,
160
- id,
161
- url,
162
- },
163
- innerBlocks: replaceUnstableBlockAttributes( block.innerBlocks ),
164
- };
165
- } );
166
- }
167
-
168
- async function deleteAllLinkedResources() {
169
- [ '/wp/v2/posts', '/wp/v2/pages' ].forEach( async ( path ) => {
170
- const items = await rest( { path } );
171
-
172
- for ( const item of items ) {
173
- await rest( {
174
- method: 'DELETE',
175
- path: `${ path }/${ item.id }?force=true`,
176
- } );
177
- }
178
- } );
179
- }
180
-
181
- async function openMenuActionsDropdown() {
182
- const menuActionsDropdown = await page.waitForXPath(
183
- '//*[@role="region"][@aria-label="Navigation top bar"]//*[@class="edit-navigation-menu-actions"]//button[@aria-expanded="false"]'
184
- );
185
- await menuActionsDropdown.click();
186
- }
187
-
188
- async function getMenuItem( menuItemName ) {
189
- return await page
190
- .waitForXPath(
191
- `//*[@role="group"]//*[@role="menuitemradio"]/span[text()="${ menuItemName }"]`
192
- )
193
- .catch( ( error ) => {
194
- if ( error.name !== 'TimeoutError' ) {
195
- throw error;
196
- } else {
197
- return null;
198
- }
199
- } );
200
- }
201
-
202
- describe.skip( 'Navigation editor', () => {
203
- useExperimentalFeatures( [ '#gutenberg-navigation' ] );
204
-
205
- beforeAll( async () => {
206
- await deleteAllMenus();
207
- await deleteAllLinkedResources();
208
- } );
209
-
210
- afterEach( async () => {
211
- await deleteAllMenus();
212
- await deleteAllLinkedResources();
213
- await setUpResponseMocking( [] );
214
- } );
215
-
216
- it( 'allows creation of a menu when there are no current menu items', async () => {
217
- await visitNavigationEditor();
218
- await setUpResponseMocking( [
219
- ...getPagesMocks( {
220
- GET: [
221
- {
222
- type: 'page',
223
- id: 1,
224
- link: 'https://example.com/1',
225
- title: {
226
- rendered: 'My page',
227
- },
228
- },
229
- ],
230
- } ),
231
- ] );
232
-
233
- // Wait for the header to show that no menus are available.
234
- await page.waitForXPath( '//h3[.="Create your first menu"]', {
235
- visible: true,
236
- } );
237
-
238
- await page.keyboard.type( 'Main Menu' );
239
- const createMenuButton = await page.waitForXPath(
240
- '//button[contains(., "Create menu")]'
241
- );
242
- await createMenuButton.click();
243
-
244
- // A snackbar will appear when menu creation has completed.
245
- await page.waitForXPath( '//div[contains(., "Menu created")]' );
246
-
247
- // Select the navigation block and create a block from existing pages.
248
- const navigationBlock = await page.waitForSelector(
249
- 'div[aria-label="Block: Navigation"]'
250
- );
251
- await navigationBlock.click();
252
-
253
- const addAllPagesButton = await page.waitForXPath(
254
- '//button[contains(., "Add all pages")]'
255
- );
256
- await addAllPagesButton.click();
257
-
258
- // When the block is created the root element changes from a div (for the placeholder)
259
- // to a nav (for the navigation itself). Wait for this to happen.
260
- await page.waitForSelector( 'nav[aria-label="Block: Navigation"]' );
261
-
262
- expect( await getSerializedBlocks() ).toMatchSnapshot();
263
- } );
264
-
265
- it( 'allows creation of a menu when there are existing menu items', async () => {
266
- await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
267
- await createMenu( { name: 'Test Menu 2' }, menuItemsFixture );
268
- await visitNavigationEditor();
269
-
270
- // Wait for the header to show the menu name.
271
- await page.waitForXPath( '//h2[contains(., "Test Menu 1")]', {
272
- visible: true,
273
- } );
274
-
275
- const createMenuButton = await page.waitForXPath(
276
- '//button[.="New menu"]'
277
- );
278
- await createMenuButton.click();
279
-
280
- const menuNameInputLabel = await page.waitForXPath(
281
- '//form//label[.="Menu name"]'
282
- );
283
- await menuNameInputLabel.click();
284
-
285
- await page.keyboard.type( 'New menu' );
286
- await page.keyboard.press( 'Enter' );
287
-
288
- // A snackbar will appear when menu creation has completed.
289
- await page.waitForXPath( '//div[contains(., "Menu created")]' );
290
-
291
- // An empty navigation block will appear.
292
- await page.waitForSelector( 'div[aria-label="Block: Navigation"]' );
293
-
294
- expect( await getSerializedBlocks() ).toMatchSnapshot();
295
- } );
296
-
297
- it( 'displays the first created menu when at least one menu exists', async () => {
298
- await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
299
- await createMenu( { name: 'Test Menu 2' }, menuItemsFixture );
300
-
301
- await visitNavigationEditor();
302
-
303
- // Wait for the header to show the menu name.
304
- await page.waitForXPath( '//h2[contains(., "Test Menu 1")]', {
305
- visible: true,
306
- } );
307
-
308
- // Wait for the block to be present.
309
- await page.waitForSelector( 'nav[aria-label="Block: Navigation"]' );
310
-
311
- expect( await getSerializedBlocks() ).toMatchSnapshot();
312
- } );
313
-
314
- it( 'shows the trailing block appender within the navigation block when no blocks are selected', async () => {
315
- // The test requires the presence of existing menus.
316
- await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
317
- await visitNavigationEditor();
318
-
319
- // Wait for at least one block to be present on the page.
320
- await page.waitForSelector( '.wp-block' );
321
-
322
- // And for this test to be valid, no blocks should be selected, which
323
- // should be the case when the editor loads.
324
- const selectedBlocks = await page.$$( '.wp-block.is-selected' );
325
- expect( selectedBlocks.length ).toBe( 0 );
326
-
327
- // And when no blocks are selected, the trailing appender is present.
328
- const blockListAppender = await page.waitForSelector(
329
- '.block-list-appender button[aria-label="Add block"]'
330
- );
331
- expect( blockListAppender ).toBeTruthy();
332
- } );
333
-
334
- it( 'has a disabled undo button when an existing menu is loaded', async () => {
335
- // The test requires the presence of existing menus.
336
- await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
337
- await visitNavigationEditor();
338
-
339
- // Wait for at least one block to be present on the page.
340
- await page.waitForSelector( '.wp-block' );
341
-
342
- // Check whether there's a disabled undo button.
343
- const disabledUndoButton = await page.waitForSelector(
344
- 'button[aria-label="Undo"][aria-disabled="true"]'
345
- );
346
- expect( disabledUndoButton ).toBeTruthy();
347
- } );
348
-
349
- it( 'shows a submenu when a link is selected and hides it when clicking the editor to deselect it', async () => {
350
- await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
351
- await visitNavigationEditor();
352
-
353
- // Select a submenu block with nested links in a submenu.
354
- const parentLinkXPath =
355
- '//div[@aria-label="Block: Submenu" and contains(.,"WordPress.org")]';
356
- const linkBlock = await page.waitForXPath( parentLinkXPath );
357
- await linkBlock.click();
358
-
359
- // There should be a submenu link visible.
360
- //
361
- // Submenus are hidden using `visibility: hidden` and shown using
362
- // `visibility: visible` so the visible/hidden options must be used
363
- // when selecting the elements.
364
- const submenuLinkXPath = `${ parentLinkXPath }//div[@aria-label="Block: Custom Link"]`;
365
- const submenuLinkVisible = await page.waitForXPath( submenuLinkXPath, {
366
- visible: true,
367
- } );
368
- expect( submenuLinkVisible ).toBeDefined();
369
-
370
- // Click in the top left corner of the canvas.
371
- const canvas = await page.$( '.edit-navigation-layout__content-area' );
372
- const boundingBox = await canvas.boundingBox();
373
- await page.mouse.click( boundingBox.x + 5, boundingBox.y + 5 );
374
-
375
- // There should be a submenu in the DOM, but it should be hidden.
376
- const submenuLinkHidden = await page.waitForXPath( submenuLinkXPath, {
377
- hidden: true,
378
- } );
379
- expect( submenuLinkHidden ).toBeDefined();
380
- } );
381
-
382
- it( 'displays suggestions when adding a link', async () => {
383
- await createMenu( { name: 'Test Menu 1' } );
384
- await setUpResponseMocking( [
385
- ...getSearchMocks( { GET: searchFixture } ),
386
- ] );
387
-
388
- await visitNavigationEditor();
389
-
390
- // Wait for the block to be present and start an empty block.
391
- const navBlock = await page.waitForSelector(
392
- 'div[aria-label="Block: Navigation"]'
393
- );
394
- await navBlock.click();
395
- const startEmptyButton = await page.waitForXPath(
396
- '//button[.="Start blank"]'
397
- );
398
- await startEmptyButton.click();
399
-
400
- const appender = await page.waitForSelector(
401
- 'button[aria-label="Add block"]'
402
- );
403
- await appender.click();
404
-
405
- await page.waitForSelector( 'input[aria-label="URL"]' );
406
-
407
- // The link suggestions should be searchable.
408
- for ( let i = 0; i < searchFixture.length; i++ ) {
409
- const { title, type, subtype, url } = searchFixture[ i ];
410
- const expectedURL = url.replace( 'https://', '' );
411
- const expectedType = TYPE_NAMES[ subtype || type ];
412
-
413
- await page.keyboard.type( title );
414
- const suggestionTitle = await page.waitForXPath(
415
- `//button[@role="option"]//span[.="${ title }"]`
416
- );
417
- const suggestionType = await page.waitForXPath(
418
- `//button[@role="option"]//span[.="${ expectedType }"]`
419
- );
420
- const suggestionURL = await page.waitForXPath(
421
- `//button[@role="option"]//span[.="${ expectedURL }"]`
422
- );
423
- expect( suggestionTitle ).toBeTruthy();
424
- expect( suggestionType ).toBeTruthy();
425
- expect( suggestionURL ).toBeTruthy();
426
- await pressKeyWithModifier( 'primary', 'A' );
427
- }
428
- } );
429
-
430
- describe( 'Menu name editor', () => {
431
- const initialMenuName = 'Main Menu';
432
- const nameEditorSelector = '.edit-navigation-name-editor__text-control';
433
- const inputSelector = `${ nameEditorSelector } input`;
434
-
435
- it( 'saves menu name changes', async () => {
436
- await createMenu( { name: initialMenuName } );
437
- await visitNavigationEditor();
438
-
439
- // Rename the menu and save it.
440
- const newName = 'New menu';
441
- await page.waitForSelector( inputSelector );
442
- await page.click( inputSelector );
443
- await pressKeyTimes( 'Backspace', initialMenuName.length );
444
- await page.keyboard.type( newName );
445
- await page.click( '.edit-navigation-toolbar__save-button' );
446
- await page.waitForSelector( '.components-snackbar' );
447
- await page.reload();
448
-
449
- // Expect the header to have the new name.
450
- const headerSubtitle = await page.waitForSelector(
451
- '.edit-navigation-menu-actions__subtitle'
452
- );
453
- const headerSubtitleText = await headerSubtitle.evaluate(
454
- ( element ) => element.innerText
455
- );
456
- expect( headerSubtitleText ).toBe( newName );
457
- } );
458
-
459
- // Flaky test, see https://github.com/WordPress/gutenberg/pull/34869#issuecomment-922711557.
460
- it.skip( 'does not save a menu name upon clicking save button when name is empty', async () => {
461
- await createMenu( { name: initialMenuName } );
462
- await visitNavigationEditor();
463
-
464
- // Try saving a menu with an empty name.
465
- await page.waitForSelector( inputSelector );
466
- await page.click( inputSelector );
467
- await pressKeyTimes( 'Backspace', initialMenuName.length );
468
- await page.click( '.edit-navigation-toolbar__save-button' );
469
- const snackbar = await page.waitForSelector(
470
- '.components-snackbar',
471
- { visible: true }
472
- );
473
- const snackbarText = await snackbar.evaluate(
474
- ( element ) => element.innerText
475
- );
476
- expect( snackbarText ).toBe(
477
- "Unable to save: 'A name is required for this term.'"
478
- );
479
- expect( console ).toHaveErrored(
480
- 'Failed to load resource: the server responded with a status of 500 (Internal Server Error)'
481
- );
482
- await page.reload();
483
-
484
- // Expect the header to have the old name.
485
- const headerSubtitle = await page.waitForSelector(
486
- '.edit-navigation-menu-actions__subtitle'
487
- );
488
- const headerSubtitleText = await headerSubtitle.evaluate(
489
- ( element ) => element.innerText
490
- );
491
- expect( headerSubtitleText ).toBe( initialMenuName );
492
- } );
493
- } );
494
-
495
- describe( 'Change detections', () => {
496
- beforeEach( async () => {
497
- await createMenu( { name: 'Main' } );
498
- await visitNavigationEditor();
499
- } );
500
-
501
- async function assertIsDirty( isDirty ) {
502
- let hadDialog = false;
503
-
504
- function handleOnDialog() {
505
- hadDialog = true;
506
- }
507
-
508
- try {
509
- page.on( 'dialog', handleOnDialog );
510
- await page.reload();
511
-
512
- // Ensure whether it was expected that dialog was encountered.
513
- expect( hadDialog ).toBe( isDirty );
514
- } catch ( error ) {
515
- throw error;
516
- } finally {
517
- page.removeListener( 'dialog', handleOnDialog );
518
- }
519
- }
520
-
521
- // eslint-disable-next-line jest/no-disabled-tests
522
- it.skip( 'should not prompt to confirm unsaved changes for the newly selected menu', async () => {
523
- await assertIsDirty( false );
524
- } );
525
-
526
- // eslint-disable-next-line jest/no-disabled-tests
527
- it.skip( 'should prompt to confirm unsaved changes when menu name is edited', async () => {
528
- await page.type(
529
- '.edit-navigation-name-editor__text-control input',
530
- ' Menu'
531
- );
532
-
533
- await assertIsDirty( true );
534
- } );
535
- } );
536
-
537
- describe( 'Sidebar inserter', () => {
538
- it( 'disables inserter toggle when Navigation block is in placeholder state', async () => {
539
- await createMenu( { name: 'Main Menu' } );
540
- await visitNavigationEditor();
541
-
542
- // Wait for the block to be present.
543
- await expect( {
544
- role: 'document',
545
- name: 'Block: Navigation',
546
- } ).toBeFound();
547
-
548
- // Check for the placeholder state.
549
- await expect( {
550
- role: 'button',
551
- name: 'Start blank',
552
- } ).toBeFound();
553
-
554
- // Expect the block inserter to be disabled.
555
- await expect( {
556
- name: 'Toggle block inserter',
557
- disabled: true,
558
- role: 'button',
559
- } ).toBeFound();
560
- } );
561
-
562
- it( 'enables inserter toggle when Navigation block is in editable state', async () => {
563
- await createMenu( { name: 'Main Menu' }, menuItemsFixture );
564
- await visitNavigationEditor();
565
-
566
- // Wait for the block to be present.
567
- await expect( {
568
- role: 'document',
569
- name: 'Block: Navigation',
570
- } ).toBeFound();
571
-
572
- // Expect the block inserter to be found.
573
- await expect( {
574
- name: 'Toggle block inserter',
575
- role: 'button',
576
- } ).toBeFound();
577
-
578
- // Work around bug where `find` with `disabled=false` doesn't return anything.
579
- const isEnabled = await page.$eval(
580
- '[aria-label="Toggle block inserter"]',
581
- ( element ) => ! element.disabled
582
- );
583
-
584
- expect( isEnabled ).toBeTruthy();
585
- } );
586
-
587
- it( 'toggles the inserter sidebar open and closed', async () => {
588
- await createMenu( { name: 'Main Menu' }, menuItemsFixture );
589
- await visitNavigationEditor();
590
-
591
- // Wait for the block to be present.
592
- await expect( {
593
- role: 'document',
594
- name: 'Block: Navigation',
595
- } ).toBeFound();
596
-
597
- // Expect inserter sidebar to **not** be in the DOM.
598
- await expect( {
599
- role: 'region',
600
- name: 'Block library',
601
- } ).not.toBeFound();
602
-
603
- const inserterToggle = await find( {
604
- name: 'Toggle block inserter',
605
- role: 'button',
606
- } );
607
-
608
- await inserterToggle.click();
609
-
610
- // Expect the inserter sidebar to be present in the DOM.
611
- await expect( {
612
- role: 'region',
613
- name: 'Block library',
614
- } ).toBeFound();
615
-
616
- // Expect block search input to be focused.
617
- await expect( {
618
- role: 'searchbox',
619
- name: 'Search for blocks and patterns',
620
- focused: true,
621
- } ).toBeFound();
622
- } );
623
-
624
- it( 'inserts items at end of Navigation block by default', async () => {
625
- await setUpResponseMocking( [
626
- ...getSearchMocks( { GET: searchFixture } ),
627
- ] );
628
- await createMenu( { name: 'Main Menu' }, menuItemsFixture );
629
-
630
- await visitNavigationEditor();
631
-
632
- // Wait for the block to be present.
633
- await expect( {
634
- role: 'document',
635
- name: 'Block: Navigation',
636
- } ).toBeFound();
637
-
638
- const inserterToggle = await find( {
639
- name: 'Toggle block inserter',
640
- role: 'button',
641
- } );
642
-
643
- await inserterToggle.click();
644
-
645
- // Expect the inserter sidebar to be present in the DOM.
646
- await expect( {
647
- role: 'region',
648
- name: 'Block library',
649
- } ).toBeFound();
650
-
651
- // Add Custom Link item.
652
- const customLinkOption = await find( {
653
- name: 'Custom Link',
654
- role: 'option',
655
- } );
656
-
657
- customLinkOption.click();
658
-
659
- // Expect that inserter is auto-closed.
660
- await expect( {
661
- role: 'region',
662
- name: 'Block library',
663
- } ).not.toBeFound();
664
-
665
- // Expect to be focused inside the Link UI search input.
666
- await expect( {
667
- role: 'combobox',
668
- name: 'URL',
669
- focused: true,
670
- } ).toBeFound();
671
-
672
- const [ itemToSelect ] = searchFixture;
673
-
674
- // Add Custom Link item.
675
- const [ firstSearchSuggestion ] = await findAll( {
676
- role: 'option',
677
- name: `${ itemToSelect.title } ${ itemToSelect.subtype }`,
678
- } );
679
-
680
- await firstSearchSuggestion.click();
681
-
682
- // Get the title/label of the last Nav item inside the Nav block.
683
- const lastItemAttributes = await page.evaluate( () => {
684
- const { getBlockOrder, getBlocks } =
685
- wp.data.select( 'core/block-editor' );
686
-
687
- const lockedNavigationBlock = getBlockOrder()[ 0 ];
688
-
689
- const navItemBlocks = getBlocks( lockedNavigationBlock );
690
-
691
- const { attributes } =
692
- navItemBlocks[ navItemBlocks.length - 1 ];
693
-
694
- return attributes;
695
- } );
696
-
697
- // Check the last item is the one we just inserted.
698
- expect( lastItemAttributes.label ).toEqual( itemToSelect.title );
699
- expect( lastItemAttributes.isTopLevelLink ).toBeTruthy();
700
- } );
701
- } );
702
-
703
- describe( 'Delete menu button', () => {
704
- useExperimentalFeatures( [ '#gutenberg-navigation' ] );
705
-
706
- beforeAll( async () => {
707
- await deleteAllMenus();
708
- await deleteAllLinkedResources();
709
- } );
710
-
711
- afterEach( async () => {
712
- await deleteAllMenus();
713
- await deleteAllLinkedResources();
714
- } );
715
-
716
- afterEach( async () => {
717
- await setBrowserViewport( 'large' );
718
- } );
719
- it.each( [ 'large', 'small' ] )(
720
- `should retain menu when confirmation is canceled and the viewport is %s`,
721
- async ( viewport ) => {
722
- const menuName = 'Menu delete test';
723
- await createMenu( { name: menuName }, menuItemsFixture );
724
- await visitNavigationEditor();
725
- await setBrowserViewport( viewport );
726
- // Wait for the header to show the menu name.
727
- await page.waitForXPath(
728
- `//*[@role="region"][@aria-label="Navigation top bar"]//h2[contains(text(), "${ menuName }")]`
729
- );
730
-
731
- if ( viewport === 'small' ) {
732
- const openSettingsSidebar = await page.waitForXPath(
733
- '//button[@aria-label="Settings"][@aria-expanded="false"]'
734
- );
735
- await openSettingsSidebar.click();
736
- }
737
-
738
- const deleteMenuButton = await page.waitForXPath(
739
- '//*[@role="region"][@aria-label="Navigation settings"]//button[text()="Delete menu"]'
740
- );
741
- await deleteMenuButton.click();
742
-
743
- const cancelButton = await page.waitForXPath(
744
- '//*[@role="dialog"]//button[text()="Cancel"]'
745
- );
746
- await cancelButton.click();
747
-
748
- const menuActionsDropdown = await page.waitForXPath(
749
- `//*[contains(@class,"edit-navigation-menu-actions")]//h2[text()="${ menuName }"]`
750
- );
751
- const currentSelectedMenu = await page.evaluate(
752
- ( el ) => el.textContent,
753
- menuActionsDropdown
754
- );
755
-
756
- expect( currentSelectedMenu ).toBe( menuName );
757
- }
758
- );
759
- it.each( [ 'large', 'small' ] )(
760
- `should delete menu when confirmation is confirmed and there are no other menus and the viewport is %s`,
761
- async ( viewport ) => {
762
- const menuName = 'Menu delete test';
763
- await createMenu( { name: menuName }, menuItemsFixture );
764
- await visitNavigationEditor();
765
- await setBrowserViewport( viewport );
766
- // Wait for the header to show the menu name.
767
- await page.waitForXPath(
768
- `//*[@role="region"][@aria-label="Navigation top bar"]//h2[contains(text(), "${ menuName }")]`
769
- );
770
- if ( viewport === 'small' ) {
771
- const openSettingsSidebar = await page.waitForXPath(
772
- '//button[@aria-label="Settings"][@aria-expanded="false"]'
773
- );
774
- await openSettingsSidebar.click();
775
- }
776
-
777
- const deleteMenuButton = await page.waitForXPath(
778
- '//*[@role="region"][@aria-label="Navigation settings"]//button[text()="Delete menu"]'
779
- );
780
- await deleteMenuButton.click();
781
-
782
- const confirmButton = await page.waitForXPath(
783
- '//*[@role="dialog"]//button[text()="OK"]'
784
- );
785
- await confirmButton.click();
786
-
787
- await page.waitForXPath(
788
- `//*[@role="button"][@aria-label="Dismiss this notice"]//*[text()='"${ menuName }" menu has been deleted']`
789
- );
790
-
791
- // If the "Create your first menu" prompt appears, we know there are no remaining menus,
792
- // so our test menu must have been deleted successfully.
793
- const createFirstMenuPrompt = await page.waitForXPath(
794
- '//h3[.="Create your first menu"]',
795
- {
796
- visible: true,
797
- }
798
- );
799
- const noMenusRemaining = createFirstMenuPrompt ? true : false;
800
- expect( noMenusRemaining ).toBe( true );
801
- }
802
- );
803
-
804
- it.each( [ 'large', 'small' ] )(
805
- `should delete menu when confirmation is confirmed and there are other existing menus and the viewport is %s`,
806
- async () => {
807
- const menuName = 'Menu delete test';
808
- await createMenu( { name: menuName }, menuItemsFixture );
809
- await createMenu(
810
- { name: `${ menuName } 2` },
811
- menuItemsFixture
812
- );
813
- await visitNavigationEditor();
814
- // Wait for the header to show the menu name
815
- await page.waitForXPath(
816
- `//*[@role="region"][@aria-label="Navigation top bar"]//h2[contains(text(), "${ menuName }")]`
817
- );
818
-
819
- // Confirm both test menus are present
820
- openMenuActionsDropdown();
821
- const firstTestMenuItem = await getMenuItem( menuName );
822
- const secondTestMenuItem = await getMenuItem(
823
- `${ menuName } 2`
824
- );
825
-
826
- expect( firstTestMenuItem ).not.toBeNull();
827
- expect( secondTestMenuItem ).not.toBeNull();
828
-
829
- // Delete the first test menu
830
- const deleteMenuButton = await page.waitForXPath(
831
- '//*[@role="region"][@aria-label="Navigation settings"]//button[text()="Delete menu"]'
832
- );
833
- await deleteMenuButton.click();
834
-
835
- const confirmButton = await page.waitForXPath(
836
- '//*[@role="dialog"]//button[text()="OK"]'
837
- );
838
- await confirmButton.click();
839
-
840
- await page.waitForXPath(
841
- `//*[@role="button"][@aria-label="Dismiss this notice"]//*[text()='"${ menuName }" menu has been deleted']`
842
- );
843
-
844
- openMenuActionsDropdown();
845
- const deletedTestMenuItem = await getMenuItem( menuName );
846
- expect( deletedTestMenuItem ).toBeNull();
847
- }
848
- );
849
- } );
850
- } );