@wordpress/e2e-tests 2.4.1-next.253d9b6e21.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.
- package/CHANGELOG.md +6 -0
- package/README.md +62 -0
- package/config/flaky-tests-reporter.js +94 -0
- package/config/setup-test-framework.js +10 -0
- package/jest.config.js +11 -1
- package/package.json +8 -7
- package/plugins/class-test-widget.php +5 -2
- package/plugins/iframed-block/block.json +16 -0
- package/plugins/iframed-block/editor.css +6 -0
- package/plugins/iframed-block/editor.js +18 -0
- package/plugins/iframed-block/jquery.test.js +7 -0
- package/plugins/iframed-block/script.js +7 -0
- package/plugins/iframed-block/style.css +9 -0
- package/plugins/iframed-block.php +46 -0
- package/specs/editor/blocks/buttons.test.js +30 -0
- package/specs/editor/blocks/post-title.test.js +1 -1
- package/specs/editor/plugins/__snapshots__/iframed-block.test.js.snap +7 -0
- package/specs/editor/plugins/align-hook.test.js +116 -105
- package/specs/editor/plugins/annotations.test.js +3 -3
- package/specs/editor/plugins/iframed-block.test.js +58 -0
- package/specs/editor/various/__snapshots__/copy-cut-paste-whole-blocks.test.js.snap +28 -0
- package/specs/editor/various/__snapshots__/rich-text.test.js.snap +15 -3
- package/specs/editor/various/a11y.test.js +1 -1
- package/specs/editor/various/block-deletion.test.js +2 -2
- package/specs/editor/various/block-grouping.test.js +2 -2
- package/specs/editor/various/block-mover.test.js +1 -1
- package/specs/editor/various/change-detection.test.js +2 -1
- package/specs/editor/various/copy-cut-paste-whole-blocks.test.js +92 -0
- package/specs/editor/various/embedding.test.js +1 -1
- package/specs/editor/various/inserting-blocks.test.js +23 -0
- package/specs/editor/various/keyboard-navigable-blocks.test.js +2 -2
- package/specs/editor/various/multi-block-selection.test.js +23 -0
- package/specs/editor/various/new-post.test.js +6 -3
- package/specs/editor/various/preview.test.js +5 -1
- package/specs/editor/various/rich-text.test.js +29 -1
- package/specs/editor/various/splitting-merging.test.js +48 -2
- package/specs/editor/various/writing-flow.test.js +14 -13
- package/specs/experiments/__snapshots__/navigation-editor.test.js.snap +27 -33
- package/specs/experiments/blocks/__snapshots__/navigation.test.js.snap +35 -25
- package/specs/experiments/blocks/navigation.test.js +93 -17
- package/specs/experiments/fixtures/menu-items-request-fixture.json +84 -0
- package/specs/experiments/navigation-editor.test.js +341 -231
- package/specs/experiments/template-part.test.js +6 -3
- package/specs/experiments/template-revert.test.js +1 -1
- package/specs/performance/post-editor.test.js +108 -80
- package/specs/performance/site-editor.test.js +2 -17
- package/specs/widgets/customizing-widgets.test.js +118 -7
- package/specs/widgets/editing-widgets.test.js +52 -88
- package/plugins/classic-widgets.php +0 -11
@@ -1,12 +1,21 @@
|
|
1
|
+
/**
|
2
|
+
* External dependencies
|
3
|
+
*/
|
4
|
+
// eslint-disable-next-line no-restricted-imports
|
5
|
+
import { find, findAll } from 'puppeteer-testing-library';
|
6
|
+
|
1
7
|
/**
|
2
8
|
* WordPress dependencies
|
3
9
|
*/
|
4
10
|
import {
|
5
11
|
createJSONResponse,
|
12
|
+
createMenu,
|
13
|
+
deleteAllMenus,
|
6
14
|
pressKeyTimes,
|
7
15
|
pressKeyWithModifier,
|
8
16
|
setUpResponseMocking,
|
9
17
|
visitAdminPage,
|
18
|
+
__experimentalRest as rest,
|
10
19
|
} from '@wordpress/e2e-test-utils';
|
11
20
|
import { addQueryArgs } from '@wordpress/url';
|
12
21
|
|
@@ -14,7 +23,7 @@ import { addQueryArgs } from '@wordpress/url';
|
|
14
23
|
* Internal dependencies
|
15
24
|
*/
|
16
25
|
import { useExperimentalFeatures } from '../../experimental-features';
|
17
|
-
import menuItemsFixture from './fixtures/menu-items-
|
26
|
+
import menuItemsFixture from './fixtures/menu-items-request-fixture.json';
|
18
27
|
|
19
28
|
const TYPE_NAMES = {
|
20
29
|
post: 'post',
|
@@ -23,21 +32,6 @@ const TYPE_NAMES = {
|
|
23
32
|
category: 'category',
|
24
33
|
};
|
25
34
|
|
26
|
-
const menusFixture = [
|
27
|
-
{
|
28
|
-
name: 'Test Menu 1',
|
29
|
-
slug: 'test-menu-1',
|
30
|
-
},
|
31
|
-
{
|
32
|
-
name: 'Test Menu 2',
|
33
|
-
slug: 'test-menu-2',
|
34
|
-
},
|
35
|
-
{
|
36
|
-
name: 'Test Menu 3',
|
37
|
-
slug: 'test-menu-3',
|
38
|
-
},
|
39
|
-
];
|
40
|
-
|
41
35
|
const searchFixture = [
|
42
36
|
{
|
43
37
|
id: 300,
|
@@ -69,15 +63,6 @@ const searchFixture = [
|
|
69
63
|
|
70
64
|
// Matching against variations of the same URL encoded and non-encoded
|
71
65
|
// produces the most reliable mocking.
|
72
|
-
const REST_MENUS_ROUTES = [
|
73
|
-
'/__experimental/menus',
|
74
|
-
`rest_route=${ encodeURIComponent( '/__experimental/menus' ) }`,
|
75
|
-
];
|
76
|
-
const REST_MENU_ITEMS_ROUTES = [
|
77
|
-
'/__experimental/menu-items',
|
78
|
-
`rest_route=${ encodeURIComponent( '/__experimental/menu-items' ) }`,
|
79
|
-
];
|
80
|
-
|
81
66
|
const REST_SEARCH_ROUTES = [
|
82
67
|
'/wp/v2/search',
|
83
68
|
`rest_route=${ encodeURIComponent( '/wp/v2/search' ) }`,
|
@@ -119,23 +104,6 @@ function getEndpointMocks( matchingRoutes, responsesByMethod ) {
|
|
119
104
|
}, [] );
|
120
105
|
}
|
121
106
|
|
122
|
-
function assignMockMenuIds( menus ) {
|
123
|
-
return menus.length
|
124
|
-
? menus.map( ( menu, index ) => ( {
|
125
|
-
...menu,
|
126
|
-
id: index + 1,
|
127
|
-
} ) )
|
128
|
-
: [];
|
129
|
-
}
|
130
|
-
|
131
|
-
function getMenuMocks( responsesByMethod ) {
|
132
|
-
return getEndpointMocks( REST_MENUS_ROUTES, responsesByMethod );
|
133
|
-
}
|
134
|
-
|
135
|
-
function getMenuItemMocks( responsesByMethod ) {
|
136
|
-
return getEndpointMocks( REST_MENU_ITEMS_ROUTES, responsesByMethod );
|
137
|
-
}
|
138
|
-
|
139
107
|
function getSearchMocks( responsesByMethod ) {
|
140
108
|
return getEndpointMocks( REST_SEARCH_ROUTES, responsesByMethod );
|
141
109
|
}
|
@@ -151,51 +119,100 @@ async function visitNavigationEditor() {
|
|
151
119
|
await visitAdminPage( '/admin.php', query );
|
152
120
|
}
|
153
121
|
|
122
|
+
/**
|
123
|
+
* Get a list of the editor's current blocks for use in a snapshot.
|
124
|
+
*
|
125
|
+
* @return {string} Block HTML.
|
126
|
+
*/
|
154
127
|
async function getSerializedBlocks() {
|
155
|
-
|
156
|
-
wp.
|
128
|
+
const blocks = await page.evaluate( () =>
|
129
|
+
wp.data.select( 'core/block-editor' ).getBlocks()
|
130
|
+
);
|
131
|
+
const safeBlocks = replaceUnstableBlockAttributes( blocks );
|
132
|
+
return page.evaluate(
|
133
|
+
( blocksToSerialize ) => wp.blocks.serialize( blocksToSerialize ),
|
134
|
+
safeBlocks
|
157
135
|
);
|
158
136
|
}
|
159
137
|
|
138
|
+
/**
|
139
|
+
* Some block attributes contain values that are not stable from test run to
|
140
|
+
* test run and can't be compared with a snapshot. These are typically the
|
141
|
+
* ids of posts or pages that are created prior to each test run. Replace those
|
142
|
+
* values with their types before serializing to a snapshot.
|
143
|
+
*
|
144
|
+
* @param {Array} blocks The array of block data.
|
145
|
+
*
|
146
|
+
* @return {Array} Updated array of block data.
|
147
|
+
*/
|
148
|
+
function replaceUnstableBlockAttributes( blocks ) {
|
149
|
+
return blocks?.map( ( block ) => {
|
150
|
+
const id = block.attributes.id ? typeof block.attributes.id : undefined;
|
151
|
+
const url = block.attributes.url
|
152
|
+
? typeof block.attributes.url
|
153
|
+
: undefined;
|
154
|
+
|
155
|
+
return {
|
156
|
+
...block,
|
157
|
+
attributes: {
|
158
|
+
...block.attributes,
|
159
|
+
id,
|
160
|
+
url,
|
161
|
+
},
|
162
|
+
innerBlocks: replaceUnstableBlockAttributes( block.innerBlocks ),
|
163
|
+
};
|
164
|
+
} );
|
165
|
+
}
|
166
|
+
|
167
|
+
async function deleteAllLinkedResources() {
|
168
|
+
[ '/wp/v2/posts', '/wp/v2/pages' ].forEach( async ( path ) => {
|
169
|
+
const items = await rest( { path } );
|
170
|
+
|
171
|
+
for ( const item of items ) {
|
172
|
+
await rest( {
|
173
|
+
method: 'DELETE',
|
174
|
+
path: `${ path }/${ item.id }?force=true`,
|
175
|
+
} );
|
176
|
+
}
|
177
|
+
} );
|
178
|
+
}
|
179
|
+
|
160
180
|
describe( 'Navigation editor', () => {
|
161
181
|
useExperimentalFeatures( [ '#gutenberg-navigation' ] );
|
162
182
|
|
183
|
+
beforeAll( async () => {
|
184
|
+
await deleteAllMenus();
|
185
|
+
await deleteAllLinkedResources();
|
186
|
+
} );
|
187
|
+
|
163
188
|
afterEach( async () => {
|
189
|
+
await deleteAllMenus();
|
190
|
+
await deleteAllLinkedResources();
|
164
191
|
await setUpResponseMocking( [] );
|
165
192
|
} );
|
166
193
|
|
167
194
|
it( 'allows creation of a menu when there are no current menu items', async () => {
|
168
|
-
|
169
|
-
id: 4,
|
170
|
-
description: '',
|
171
|
-
name: 'Main Menu',
|
172
|
-
slug: 'main-menu',
|
173
|
-
meta: [],
|
174
|
-
auto_add: false,
|
175
|
-
};
|
176
|
-
|
177
|
-
// Initially return nothing from the menu and menuItem endpoints
|
195
|
+
await visitNavigationEditor();
|
178
196
|
await setUpResponseMocking( [
|
179
|
-
...
|
180
|
-
|
197
|
+
...getPagesMocks( {
|
198
|
+
GET: [
|
199
|
+
{
|
200
|
+
type: 'page',
|
201
|
+
id: 1,
|
202
|
+
link: 'https://example.com/1',
|
203
|
+
title: {
|
204
|
+
rendered: 'My page',
|
205
|
+
},
|
206
|
+
},
|
207
|
+
],
|
208
|
+
} ),
|
181
209
|
] );
|
182
|
-
await visitNavigationEditor();
|
183
210
|
|
184
211
|
// Wait for the header to show that no menus are available.
|
185
212
|
await page.waitForXPath( '//h3[.="Create your first menu"]', {
|
186
213
|
visible: true,
|
187
214
|
} );
|
188
215
|
|
189
|
-
// Prepare the menu endpoint for creating a menu.
|
190
|
-
await setUpResponseMocking( [
|
191
|
-
...getMenuMocks( {
|
192
|
-
GET: [ menuPostResponse ],
|
193
|
-
POST: menuPostResponse,
|
194
|
-
} ),
|
195
|
-
...getMenuItemMocks( { GET: [] } ),
|
196
|
-
...getPagesMocks( { GET: [ {} ] } ), // mock a single page
|
197
|
-
] );
|
198
|
-
|
199
216
|
await page.keyboard.type( 'Main Menu' );
|
200
217
|
const createMenuButton = await page.waitForXPath(
|
201
218
|
'//button[contains(., "Create menu")]'
|
@@ -224,37 +241,17 @@ describe( 'Navigation editor', () => {
|
|
224
241
|
} );
|
225
242
|
|
226
243
|
it( 'allows creation of a menu when there are existing menu items', async () => {
|
227
|
-
|
228
|
-
|
229
|
-
description: '',
|
230
|
-
name: 'New Menu',
|
231
|
-
slug: 'new-menu',
|
232
|
-
meta: [],
|
233
|
-
auto_add: false,
|
234
|
-
};
|
235
|
-
|
236
|
-
await setUpResponseMocking( [
|
237
|
-
...getMenuMocks( {
|
238
|
-
GET: assignMockMenuIds( menusFixture ),
|
239
|
-
POST: menuPostResponse,
|
240
|
-
} ),
|
241
|
-
...getMenuItemMocks( { GET: menuItemsFixture } ),
|
242
|
-
] );
|
244
|
+
await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
|
245
|
+
await createMenu( { name: 'Test Menu 2' }, menuItemsFixture );
|
243
246
|
await visitNavigationEditor();
|
244
247
|
|
245
248
|
// Wait for the header to show the menu name.
|
246
|
-
await page.waitForXPath( '//h2[contains(., "
|
249
|
+
await page.waitForXPath( '//h2[contains(., "Test Menu 1")]', {
|
247
250
|
visible: true,
|
248
251
|
} );
|
249
252
|
|
250
|
-
// Open up the menu creation dialog and create a new menu.
|
251
|
-
const switchMenuButton = await page.waitForXPath(
|
252
|
-
'//button[.="Switch menu"]'
|
253
|
-
);
|
254
|
-
await switchMenuButton.click();
|
255
|
-
|
256
253
|
const createMenuButton = await page.waitForXPath(
|
257
|
-
'//button[.="
|
254
|
+
'//button[.="New menu"]'
|
258
255
|
);
|
259
256
|
await createMenuButton.click();
|
260
257
|
|
@@ -263,17 +260,6 @@ describe( 'Navigation editor', () => {
|
|
263
260
|
);
|
264
261
|
await menuNameInputLabel.click();
|
265
262
|
|
266
|
-
await setUpResponseMocking( [
|
267
|
-
...getMenuMocks( {
|
268
|
-
GET: assignMockMenuIds( [
|
269
|
-
...menusFixture,
|
270
|
-
{ name: 'New menu', slug: 'new-menu' },
|
271
|
-
] ),
|
272
|
-
POST: menuPostResponse,
|
273
|
-
} ),
|
274
|
-
...getMenuItemMocks( { GET: [] } ),
|
275
|
-
] );
|
276
|
-
|
277
263
|
await page.keyboard.type( 'New menu' );
|
278
264
|
await page.keyboard.press( 'Enter' );
|
279
265
|
|
@@ -286,15 +272,14 @@ describe( 'Navigation editor', () => {
|
|
286
272
|
expect( await getSerializedBlocks() ).toMatchSnapshot();
|
287
273
|
} );
|
288
274
|
|
289
|
-
it( 'displays the first menu
|
290
|
-
await
|
291
|
-
|
292
|
-
|
293
|
-
] );
|
275
|
+
it( 'displays the first created menu when at least one menu exists', async () => {
|
276
|
+
await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
|
277
|
+
await createMenu( { name: 'Test Menu 2' }, menuItemsFixture );
|
278
|
+
|
294
279
|
await visitNavigationEditor();
|
295
280
|
|
296
281
|
// Wait for the header to show the menu name.
|
297
|
-
await page.waitForXPath( '//h2[contains(., "
|
282
|
+
await page.waitForXPath( '//h2[contains(., "Test Menu 1")]', {
|
298
283
|
visible: true,
|
299
284
|
} );
|
300
285
|
|
@@ -304,16 +289,48 @@ describe( 'Navigation editor', () => {
|
|
304
289
|
expect( await getSerializedBlocks() ).toMatchSnapshot();
|
305
290
|
} );
|
306
291
|
|
292
|
+
it( 'shows the trailing block appender within the navigation block when no blocks are selected', async () => {
|
293
|
+
// The test requires the presence of existing menus.
|
294
|
+
await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
|
295
|
+
await visitNavigationEditor();
|
296
|
+
|
297
|
+
// Wait for at least one block to be present on the page.
|
298
|
+
await page.waitForSelector( '.wp-block' );
|
299
|
+
|
300
|
+
// And for this test to be valid, no blocks should be selected, which
|
301
|
+
// should be the case when the editor loads.
|
302
|
+
const selectedBlocks = await page.$$( '.wp-block.is-selected' );
|
303
|
+
expect( selectedBlocks.length ).toBe( 0 );
|
304
|
+
|
305
|
+
// And when no blocks are selected, the trailing appender is present.
|
306
|
+
const blockListAppender = await page.waitForSelector(
|
307
|
+
'.block-list-appender button[aria-label="Add block"]'
|
308
|
+
);
|
309
|
+
expect( blockListAppender ).toBeTruthy();
|
310
|
+
} );
|
311
|
+
|
312
|
+
it( 'has a disabled undo button when an existing menu is loaded', async () => {
|
313
|
+
// The test requires the presence of existing menus.
|
314
|
+
await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
|
315
|
+
await visitNavigationEditor();
|
316
|
+
|
317
|
+
// Wait for at least one block to be present on the page.
|
318
|
+
await page.waitForSelector( '.wp-block' );
|
319
|
+
|
320
|
+
// Check whether there's a disabled undo button.
|
321
|
+
const disabledUndoButton = await page.waitForSelector(
|
322
|
+
'button[aria-label="Undo"][aria-disabled="true"]'
|
323
|
+
);
|
324
|
+
expect( disabledUndoButton ).toBeTruthy();
|
325
|
+
} );
|
326
|
+
|
307
327
|
it( 'shows a submenu when a link is selected and hides it when clicking the editor to deselect it', async () => {
|
308
|
-
await
|
309
|
-
...getMenuMocks( { GET: assignMockMenuIds( menusFixture ) } ),
|
310
|
-
...getMenuItemMocks( { GET: menuItemsFixture } ),
|
311
|
-
] );
|
328
|
+
await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
|
312
329
|
await visitNavigationEditor();
|
313
330
|
|
314
|
-
// Select a
|
331
|
+
// Select a submenu block with nested links in a submenu.
|
315
332
|
const parentLinkXPath =
|
316
|
-
'//div[@aria-label="Block:
|
333
|
+
'//div[@aria-label="Block: Submenu" and contains(.,"WordPress.org")]';
|
317
334
|
const linkBlock = await page.waitForXPath( parentLinkXPath );
|
318
335
|
await linkBlock.click();
|
319
336
|
|
@@ -341,8 +358,8 @@ describe( 'Navigation editor', () => {
|
|
341
358
|
} );
|
342
359
|
|
343
360
|
it( 'displays suggestions when adding a link', async () => {
|
361
|
+
await createMenu( { name: 'Test Menu 1' } );
|
344
362
|
await setUpResponseMocking( [
|
345
|
-
...getMenuMocks( { GET: assignMockMenuIds( menusFixture ) } ),
|
346
363
|
...getSearchMocks( { GET: searchFixture } ),
|
347
364
|
] );
|
348
365
|
|
@@ -354,7 +371,7 @@ describe( 'Navigation editor', () => {
|
|
354
371
|
);
|
355
372
|
await navBlock.click();
|
356
373
|
const startEmptyButton = await page.waitForXPath(
|
357
|
-
'//button[.="Start
|
374
|
+
'//button[.="Start blank"]'
|
358
375
|
);
|
359
376
|
await startEmptyButton.click();
|
360
377
|
|
@@ -363,11 +380,6 @@ describe( 'Navigation editor', () => {
|
|
363
380
|
);
|
364
381
|
await appender.click();
|
365
382
|
|
366
|
-
const linkInserterItem = await page.waitForXPath(
|
367
|
-
'//button[@role="option"]//span[.="Custom Link"]'
|
368
|
-
);
|
369
|
-
await linkInserterItem.click();
|
370
|
-
|
371
383
|
await page.waitForSelector( 'input[aria-label="URL"]' );
|
372
384
|
|
373
385
|
// The link suggestions should be searchable.
|
@@ -398,144 +410,72 @@ describe( 'Navigation editor', () => {
|
|
398
410
|
const nameEditorSelector = '.edit-navigation-name-editor__text-control';
|
399
411
|
const inputSelector = `${ nameEditorSelector } input`;
|
400
412
|
|
401
|
-
|
402
|
-
|
403
|
-
id: 4,
|
404
|
-
description: '',
|
405
|
-
name: initialMenuName,
|
406
|
-
slug: 'main-menu',
|
407
|
-
meta: [],
|
408
|
-
auto_add: false,
|
409
|
-
};
|
410
|
-
|
411
|
-
await setUpResponseMocking( [
|
412
|
-
...getMenuMocks( {
|
413
|
-
GET: [ menuPostResponse ],
|
414
|
-
POST: menuPostResponse,
|
415
|
-
} ),
|
416
|
-
...getMenuItemMocks( { GET: [] } ),
|
417
|
-
] );
|
418
|
-
|
413
|
+
it( 'saves menu name changes', async () => {
|
414
|
+
await createMenu( { name: initialMenuName } );
|
419
415
|
await visitNavigationEditor();
|
420
416
|
|
421
|
-
//
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
afterEach( async () => {
|
426
|
-
await setUpResponseMocking( [] );
|
427
|
-
} );
|
428
|
-
|
429
|
-
it( 'is displayed in inspector additions', async () => {
|
430
|
-
const nameControl = await page.$( nameEditorSelector );
|
431
|
-
expect( nameControl ).toBeDefined();
|
432
|
-
} );
|
433
|
-
|
434
|
-
it( 'saves menu name upon clicking save button', async () => {
|
435
|
-
const newName = 'newName';
|
436
|
-
const menuPostResponse = {
|
437
|
-
id: 4,
|
438
|
-
description: '',
|
439
|
-
name: newName,
|
440
|
-
slug: 'main-menu',
|
441
|
-
meta: [],
|
442
|
-
auto_add: false,
|
443
|
-
};
|
444
|
-
|
445
|
-
await setUpResponseMocking( [
|
446
|
-
...getMenuMocks( {
|
447
|
-
GET: [ menuPostResponse ],
|
448
|
-
POST: menuPostResponse,
|
449
|
-
} ),
|
450
|
-
...getMenuItemMocks( { GET: [] } ),
|
451
|
-
] );
|
452
|
-
|
453
|
-
// Ensure there is focus.
|
454
|
-
await page.focus( inputSelector );
|
417
|
+
// Rename the menu and save it.
|
418
|
+
const newName = 'New menu';
|
419
|
+
await page.waitForSelector( inputSelector );
|
420
|
+
await page.click( inputSelector );
|
455
421
|
await pressKeyTimes( 'Backspace', initialMenuName.length );
|
456
422
|
await page.keyboard.type( newName );
|
457
|
-
|
458
|
-
const saveButton = await page.$(
|
459
|
-
'.edit-navigation-toolbar__save-button'
|
460
|
-
);
|
461
|
-
await saveButton.click();
|
423
|
+
await page.click( '.edit-navigation-toolbar__save-button' );
|
462
424
|
await page.waitForSelector( '.components-snackbar' );
|
425
|
+
await page.reload();
|
426
|
+
|
427
|
+
// Expect the header to have the new name.
|
463
428
|
const headerSubtitle = await page.waitForSelector(
|
464
|
-
'.edit-navigation-
|
429
|
+
'.edit-navigation-menu-actions__subtitle'
|
465
430
|
);
|
466
|
-
expect( headerSubtitle ).toBeTruthy();
|
467
431
|
const headerSubtitleText = await headerSubtitle.evaluate(
|
468
432
|
( element ) => element.innerText
|
469
433
|
);
|
470
|
-
expect( headerSubtitleText ).toBe(
|
434
|
+
expect( headerSubtitleText ).toBe( newName );
|
471
435
|
} );
|
472
436
|
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
name: initialMenuName,
|
478
|
-
slug: 'main-menu',
|
479
|
-
meta: [],
|
480
|
-
auto_add: false,
|
481
|
-
};
|
482
|
-
|
483
|
-
await setUpResponseMocking( [
|
484
|
-
...getMenuMocks( {
|
485
|
-
GET: [ menuPostResponse ],
|
486
|
-
POST: menuPostResponse,
|
487
|
-
} ),
|
488
|
-
...getMenuItemMocks( { GET: [] } ),
|
489
|
-
] );
|
437
|
+
// Flaky test, see https://github.com/WordPress/gutenberg/pull/34869#issuecomment-922711557.
|
438
|
+
it.skip( 'does not save a menu name upon clicking save button when name is empty', async () => {
|
439
|
+
await createMenu( { name: initialMenuName } );
|
440
|
+
await visitNavigationEditor();
|
490
441
|
|
491
|
-
//
|
492
|
-
await page.
|
442
|
+
// Try saving a menu with an empty name.
|
443
|
+
await page.waitForSelector( inputSelector );
|
444
|
+
await page.click( inputSelector );
|
493
445
|
await pressKeyTimes( 'Backspace', initialMenuName.length );
|
494
|
-
|
495
|
-
const
|
496
|
-
'.
|
446
|
+
await page.click( '.edit-navigation-toolbar__save-button' );
|
447
|
+
const snackbar = await page.waitForSelector(
|
448
|
+
'.components-snackbar',
|
449
|
+
{ visible: true }
|
497
450
|
);
|
498
|
-
await
|
499
|
-
|
451
|
+
const snackbarText = await snackbar.evaluate(
|
452
|
+
( element ) => element.innerText
|
453
|
+
);
|
454
|
+
expect( snackbarText ).toBe(
|
455
|
+
"Unable to save: 'A name is required for this term.'"
|
456
|
+
);
|
457
|
+
expect( console ).toHaveErrored(
|
458
|
+
'Failed to load resource: the server responded with a status of 500 (Internal Server Error)'
|
459
|
+
);
|
460
|
+
await page.reload();
|
461
|
+
|
462
|
+
// Expect the header to have the old name.
|
500
463
|
const headerSubtitle = await page.waitForSelector(
|
501
|
-
'.edit-navigation-
|
464
|
+
'.edit-navigation-menu-actions__subtitle'
|
502
465
|
);
|
503
|
-
expect( headerSubtitle ).toBeTruthy();
|
504
466
|
const headerSubtitleText = await headerSubtitle.evaluate(
|
505
467
|
( element ) => element.innerText
|
506
468
|
);
|
507
|
-
expect( headerSubtitleText ).toBe(
|
508
|
-
`Editing: ${ initialMenuName }`
|
509
|
-
);
|
469
|
+
expect( headerSubtitleText ).toBe( initialMenuName );
|
510
470
|
} );
|
511
471
|
} );
|
512
472
|
|
513
473
|
describe( 'Change detections', () => {
|
514
474
|
beforeEach( async () => {
|
515
|
-
|
516
|
-
id: 4,
|
517
|
-
description: '',
|
518
|
-
name: 'Main',
|
519
|
-
slug: 'main-menu',
|
520
|
-
meta: [],
|
521
|
-
auto_add: false,
|
522
|
-
};
|
523
|
-
|
524
|
-
await setUpResponseMocking( [
|
525
|
-
...getMenuMocks( {
|
526
|
-
GET: [ menuPostResponse ],
|
527
|
-
POST: menuPostResponse,
|
528
|
-
} ),
|
529
|
-
...getMenuItemMocks( { GET: [] } ),
|
530
|
-
] );
|
531
|
-
|
475
|
+
await createMenu( { name: 'Main' } );
|
532
476
|
await visitNavigationEditor();
|
533
477
|
} );
|
534
478
|
|
535
|
-
afterEach( async () => {
|
536
|
-
await setUpResponseMocking( [] );
|
537
|
-
} );
|
538
|
-
|
539
479
|
async function assertIsDirty( isDirty ) {
|
540
480
|
let hadDialog = false;
|
541
481
|
|
@@ -556,10 +496,12 @@ describe( 'Navigation editor', () => {
|
|
556
496
|
}
|
557
497
|
}
|
558
498
|
|
499
|
+
// eslint-disable-next-line jest/no-disabled-tests
|
559
500
|
it.skip( 'should not prompt to confirm unsaved changes for the newly selected menu', async () => {
|
560
501
|
await assertIsDirty( false );
|
561
502
|
} );
|
562
503
|
|
504
|
+
// eslint-disable-next-line jest/no-disabled-tests
|
563
505
|
it.skip( 'should prompt to confirm unsaved changes when menu name is edited', async () => {
|
564
506
|
await page.type(
|
565
507
|
'.edit-navigation-name-editor__text-control input',
|
@@ -569,4 +511,172 @@ describe( 'Navigation editor', () => {
|
|
569
511
|
await assertIsDirty( true );
|
570
512
|
} );
|
571
513
|
} );
|
514
|
+
|
515
|
+
describe( 'Sidebar inserter', () => {
|
516
|
+
it( 'disables inserter toggle when Navigation block is in placeholder state', async () => {
|
517
|
+
await createMenu( { name: 'Main Menu' } );
|
518
|
+
await visitNavigationEditor();
|
519
|
+
|
520
|
+
// Wait for the block to be present.
|
521
|
+
await expect( {
|
522
|
+
role: 'document',
|
523
|
+
name: 'Block: Navigation',
|
524
|
+
} ).toBeFound();
|
525
|
+
|
526
|
+
// Check for the placeholder state
|
527
|
+
await expect( {
|
528
|
+
role: 'button',
|
529
|
+
name: 'Start blank',
|
530
|
+
} ).toBeFound();
|
531
|
+
|
532
|
+
// Expect the block inserter to be disabled.
|
533
|
+
await expect( {
|
534
|
+
name: 'Toggle block inserter',
|
535
|
+
disabled: true,
|
536
|
+
role: 'button',
|
537
|
+
} ).toBeFound();
|
538
|
+
} );
|
539
|
+
|
540
|
+
it( 'enables inserter toggle when Navigation block is in editable state', async () => {
|
541
|
+
await createMenu( { name: 'Main Menu' }, menuItemsFixture );
|
542
|
+
await visitNavigationEditor();
|
543
|
+
|
544
|
+
// Wait for the block to be present.
|
545
|
+
await expect( {
|
546
|
+
role: 'document',
|
547
|
+
name: 'Block: Navigation',
|
548
|
+
} ).toBeFound();
|
549
|
+
|
550
|
+
// Expect the block inserter to be found.
|
551
|
+
await expect( {
|
552
|
+
name: 'Toggle block inserter',
|
553
|
+
role: 'button',
|
554
|
+
} ).toBeFound();
|
555
|
+
|
556
|
+
// Work around bug where `find` with `disabled=false` doesn't return anything.
|
557
|
+
const isEnabled = await page.$eval(
|
558
|
+
'[aria-label="Toggle block inserter"]',
|
559
|
+
( element ) => ! element.disabled
|
560
|
+
);
|
561
|
+
|
562
|
+
expect( isEnabled ).toBeTruthy();
|
563
|
+
} );
|
564
|
+
|
565
|
+
it( 'toggles the inserter sidebar open and closed', async () => {
|
566
|
+
await createMenu( { name: 'Main Menu' }, menuItemsFixture );
|
567
|
+
await visitNavigationEditor();
|
568
|
+
|
569
|
+
// Wait for the block to be present.
|
570
|
+
await expect( {
|
571
|
+
role: 'document',
|
572
|
+
name: 'Block: Navigation',
|
573
|
+
} ).toBeFound();
|
574
|
+
|
575
|
+
// Expect inserter sidebar to **not** be in the DOM.
|
576
|
+
await expect( {
|
577
|
+
role: 'region',
|
578
|
+
name: 'Block library',
|
579
|
+
} ).not.toBeFound();
|
580
|
+
|
581
|
+
const inserterToggle = await find( {
|
582
|
+
name: 'Toggle block inserter',
|
583
|
+
role: 'button',
|
584
|
+
} );
|
585
|
+
|
586
|
+
await inserterToggle.click();
|
587
|
+
|
588
|
+
// Expect the inserter sidebar to be present in the DOM.
|
589
|
+
await expect( {
|
590
|
+
role: 'region',
|
591
|
+
name: 'Block library',
|
592
|
+
} ).toBeFound();
|
593
|
+
|
594
|
+
// Expect block search input to be focused.
|
595
|
+
await expect( {
|
596
|
+
role: 'searchbox',
|
597
|
+
name: 'Search for blocks and patterns',
|
598
|
+
focused: true,
|
599
|
+
} ).toBeFound();
|
600
|
+
} );
|
601
|
+
|
602
|
+
it( 'inserts items at end of Navigation block by default', async () => {
|
603
|
+
await setUpResponseMocking( [
|
604
|
+
...getSearchMocks( { GET: searchFixture } ),
|
605
|
+
] );
|
606
|
+
await createMenu( { name: 'Main Menu' }, menuItemsFixture );
|
607
|
+
|
608
|
+
await visitNavigationEditor();
|
609
|
+
|
610
|
+
// Wait for the block to be present.
|
611
|
+
await expect( {
|
612
|
+
role: 'document',
|
613
|
+
name: 'Block: Navigation',
|
614
|
+
} ).toBeFound();
|
615
|
+
|
616
|
+
const inserterToggle = await find( {
|
617
|
+
name: 'Toggle block inserter',
|
618
|
+
role: 'button',
|
619
|
+
} );
|
620
|
+
|
621
|
+
await inserterToggle.click();
|
622
|
+
|
623
|
+
// Expect the inserter sidebar to be present in the DOM.
|
624
|
+
await expect( {
|
625
|
+
role: 'region',
|
626
|
+
name: 'Block library',
|
627
|
+
} ).toBeFound();
|
628
|
+
|
629
|
+
// Add Custom Link item.
|
630
|
+
const customLinkOption = await find( {
|
631
|
+
name: 'Custom Link',
|
632
|
+
role: 'option',
|
633
|
+
} );
|
634
|
+
|
635
|
+
customLinkOption.click();
|
636
|
+
|
637
|
+
// Expect that inserter is auto-closed.
|
638
|
+
await expect( {
|
639
|
+
role: 'region',
|
640
|
+
name: 'Block library',
|
641
|
+
} ).not.toBeFound();
|
642
|
+
|
643
|
+
// Expect to be focused inside the Link UI search input.
|
644
|
+
await expect( {
|
645
|
+
role: 'combobox',
|
646
|
+
name: 'URL',
|
647
|
+
focused: true,
|
648
|
+
} ).toBeFound();
|
649
|
+
|
650
|
+
const [ itemToSelect ] = searchFixture;
|
651
|
+
|
652
|
+
// Add Custom Link item.
|
653
|
+
const [ firstSearchSuggestion ] = await findAll( {
|
654
|
+
role: 'option',
|
655
|
+
name: `${ itemToSelect.title } ${ itemToSelect.subtype }`,
|
656
|
+
} );
|
657
|
+
|
658
|
+
await firstSearchSuggestion.click();
|
659
|
+
|
660
|
+
// Get the title/label of the last Nav item inside the Nav block.
|
661
|
+
const lastItemAttributes = await page.evaluate( () => {
|
662
|
+
const { getBlockOrder, getBlocks } = wp.data.select(
|
663
|
+
'core/block-editor'
|
664
|
+
);
|
665
|
+
|
666
|
+
const lockedNavigationBlock = getBlockOrder()[ 0 ];
|
667
|
+
|
668
|
+
const navItemBlocks = getBlocks( lockedNavigationBlock );
|
669
|
+
|
670
|
+
const { attributes } = navItemBlocks[
|
671
|
+
navItemBlocks.length - 1
|
672
|
+
];
|
673
|
+
|
674
|
+
return attributes;
|
675
|
+
} );
|
676
|
+
|
677
|
+
// Check the last item is the one we just inserted
|
678
|
+
expect( lastItemAttributes.label ).toEqual( itemToSelect.title );
|
679
|
+
expect( lastItemAttributes.isTopLevelLink ).toBeTruthy();
|
680
|
+
} );
|
681
|
+
} );
|
572
682
|
} );
|