@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.
- package/README.md +2 -2
- package/config/flaky-tests-reporter.js +94 -0
- package/config/setup-test-framework.js +7 -0
- package/jest.config.js +11 -1
- package/package.json +6 -5
- 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/plugins/__snapshots__/iframed-block.test.js.snap +7 -0
- package/specs/editor/plugins/align-hook.test.js +116 -105
- 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/block-grouping.test.js +2 -2
- 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/rich-text.test.js +29 -1
- package/specs/editor/various/writing-flow.test.js +4 -2
- package/specs/experiments/__snapshots__/navigation-editor.test.js.snap +27 -33
- package/specs/experiments/blocks/__snapshots__/navigation.test.js.snap +29 -19
- 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 +332 -233
- package/specs/experiments/template-revert.test.js +1 -1
- package/specs/performance/site-editor.test.js +2 -17
- package/specs/widgets/customizing-widgets.test.js +94 -1
- package/specs/widgets/editing-widgets.test.js +6 -0
@@ -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,48 +119,81 @@ 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()
|
157
130
|
);
|
131
|
+
const safeBlocks = replaceUnstableBlockAttributes( blocks );
|
132
|
+
return page.evaluate(
|
133
|
+
( blocksToSerialize ) => wp.blocks.serialize( blocksToSerialize ),
|
134
|
+
safeBlocks
|
135
|
+
);
|
136
|
+
}
|
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
|
+
} );
|
158
178
|
}
|
159
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
|
-
const menuPostResponse = {
|
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
|
178
|
-
await setUpResponseMocking( [
|
179
|
-
...getMenuMocks( { GET: [] } ),
|
180
|
-
...getMenuItemMocks( { GET: [] } ),
|
181
|
-
] );
|
182
195
|
await visitNavigationEditor();
|
183
|
-
|
184
|
-
// Wait for the header to show that no menus are available.
|
185
|
-
await page.waitForXPath( '//h3[.="Create your first menu"]', {
|
186
|
-
visible: true,
|
187
|
-
} );
|
188
|
-
|
189
|
-
// Prepare the menu endpoint for creating a menu.
|
190
196
|
await setUpResponseMocking( [
|
191
|
-
...getMenuMocks( {
|
192
|
-
GET: [ menuPostResponse ],
|
193
|
-
POST: menuPostResponse,
|
194
|
-
} ),
|
195
|
-
...getMenuItemMocks( { GET: [] } ),
|
196
197
|
...getPagesMocks( {
|
197
198
|
GET: [
|
198
199
|
{
|
@@ -207,6 +208,11 @@ describe( 'Navigation editor', () => {
|
|
207
208
|
} ),
|
208
209
|
] );
|
209
210
|
|
211
|
+
// Wait for the header to show that no menus are available.
|
212
|
+
await page.waitForXPath( '//h3[.="Create your first menu"]', {
|
213
|
+
visible: true,
|
214
|
+
} );
|
215
|
+
|
210
216
|
await page.keyboard.type( 'Main Menu' );
|
211
217
|
const createMenuButton = await page.waitForXPath(
|
212
218
|
'//button[contains(., "Create menu")]'
|
@@ -235,37 +241,17 @@ describe( 'Navigation editor', () => {
|
|
235
241
|
} );
|
236
242
|
|
237
243
|
it( 'allows creation of a menu when there are existing menu items', async () => {
|
238
|
-
|
239
|
-
|
240
|
-
description: '',
|
241
|
-
name: 'New Menu',
|
242
|
-
slug: 'new-menu',
|
243
|
-
meta: [],
|
244
|
-
auto_add: false,
|
245
|
-
};
|
246
|
-
|
247
|
-
await setUpResponseMocking( [
|
248
|
-
...getMenuMocks( {
|
249
|
-
GET: assignMockMenuIds( menusFixture ),
|
250
|
-
POST: menuPostResponse,
|
251
|
-
} ),
|
252
|
-
...getMenuItemMocks( { GET: menuItemsFixture } ),
|
253
|
-
] );
|
244
|
+
await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
|
245
|
+
await createMenu( { name: 'Test Menu 2' }, menuItemsFixture );
|
254
246
|
await visitNavigationEditor();
|
255
247
|
|
256
248
|
// Wait for the header to show the menu name.
|
257
|
-
await page.waitForXPath( '//h2[contains(., "
|
249
|
+
await page.waitForXPath( '//h2[contains(., "Test Menu 1")]', {
|
258
250
|
visible: true,
|
259
251
|
} );
|
260
252
|
|
261
|
-
// Open up the menu creation dialog and create a new menu.
|
262
|
-
const switchMenuButton = await page.waitForXPath(
|
263
|
-
'//button[.="Switch menu"]'
|
264
|
-
);
|
265
|
-
await switchMenuButton.click();
|
266
|
-
|
267
253
|
const createMenuButton = await page.waitForXPath(
|
268
|
-
'//button[.="
|
254
|
+
'//button[.="New menu"]'
|
269
255
|
);
|
270
256
|
await createMenuButton.click();
|
271
257
|
|
@@ -274,17 +260,6 @@ describe( 'Navigation editor', () => {
|
|
274
260
|
);
|
275
261
|
await menuNameInputLabel.click();
|
276
262
|
|
277
|
-
await setUpResponseMocking( [
|
278
|
-
...getMenuMocks( {
|
279
|
-
GET: assignMockMenuIds( [
|
280
|
-
...menusFixture,
|
281
|
-
{ name: 'New menu', slug: 'new-menu' },
|
282
|
-
] ),
|
283
|
-
POST: menuPostResponse,
|
284
|
-
} ),
|
285
|
-
...getMenuItemMocks( { GET: [] } ),
|
286
|
-
] );
|
287
|
-
|
288
263
|
await page.keyboard.type( 'New menu' );
|
289
264
|
await page.keyboard.press( 'Enter' );
|
290
265
|
|
@@ -297,15 +272,14 @@ describe( 'Navigation editor', () => {
|
|
297
272
|
expect( await getSerializedBlocks() ).toMatchSnapshot();
|
298
273
|
} );
|
299
274
|
|
300
|
-
it( 'displays the first menu
|
301
|
-
await
|
302
|
-
|
303
|
-
|
304
|
-
] );
|
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
|
+
|
305
279
|
await visitNavigationEditor();
|
306
280
|
|
307
281
|
// Wait for the header to show the menu name.
|
308
|
-
await page.waitForXPath( '//h2[contains(., "
|
282
|
+
await page.waitForXPath( '//h2[contains(., "Test Menu 1")]', {
|
309
283
|
visible: true,
|
310
284
|
} );
|
311
285
|
|
@@ -315,16 +289,48 @@ describe( 'Navigation editor', () => {
|
|
315
289
|
expect( await getSerializedBlocks() ).toMatchSnapshot();
|
316
290
|
} );
|
317
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
|
+
|
318
327
|
it( 'shows a submenu when a link is selected and hides it when clicking the editor to deselect it', async () => {
|
319
|
-
await
|
320
|
-
...getMenuMocks( { GET: assignMockMenuIds( menusFixture ) } ),
|
321
|
-
...getMenuItemMocks( { GET: menuItemsFixture } ),
|
322
|
-
] );
|
328
|
+
await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
|
323
329
|
await visitNavigationEditor();
|
324
330
|
|
325
|
-
// Select a
|
331
|
+
// Select a submenu block with nested links in a submenu.
|
326
332
|
const parentLinkXPath =
|
327
|
-
'//div[@aria-label="Block:
|
333
|
+
'//div[@aria-label="Block: Submenu" and contains(.,"WordPress.org")]';
|
328
334
|
const linkBlock = await page.waitForXPath( parentLinkXPath );
|
329
335
|
await linkBlock.click();
|
330
336
|
|
@@ -352,8 +358,8 @@ describe( 'Navigation editor', () => {
|
|
352
358
|
} );
|
353
359
|
|
354
360
|
it( 'displays suggestions when adding a link', async () => {
|
361
|
+
await createMenu( { name: 'Test Menu 1' } );
|
355
362
|
await setUpResponseMocking( [
|
356
|
-
...getMenuMocks( { GET: assignMockMenuIds( menusFixture ) } ),
|
357
363
|
...getSearchMocks( { GET: searchFixture } ),
|
358
364
|
] );
|
359
365
|
|
@@ -374,11 +380,6 @@ describe( 'Navigation editor', () => {
|
|
374
380
|
);
|
375
381
|
await appender.click();
|
376
382
|
|
377
|
-
const linkInserterItem = await page.waitForXPath(
|
378
|
-
'//button[@role="option"]//span[.="Custom Link"]'
|
379
|
-
);
|
380
|
-
await linkInserterItem.click();
|
381
|
-
|
382
383
|
await page.waitForSelector( 'input[aria-label="URL"]' );
|
383
384
|
|
384
385
|
// The link suggestions should be searchable.
|
@@ -409,144 +410,72 @@ describe( 'Navigation editor', () => {
|
|
409
410
|
const nameEditorSelector = '.edit-navigation-name-editor__text-control';
|
410
411
|
const inputSelector = `${ nameEditorSelector } input`;
|
411
412
|
|
412
|
-
|
413
|
-
|
414
|
-
id: 4,
|
415
|
-
description: '',
|
416
|
-
name: initialMenuName,
|
417
|
-
slug: 'main-menu',
|
418
|
-
meta: [],
|
419
|
-
auto_add: false,
|
420
|
-
};
|
421
|
-
|
422
|
-
await setUpResponseMocking( [
|
423
|
-
...getMenuMocks( {
|
424
|
-
GET: [ menuPostResponse ],
|
425
|
-
POST: menuPostResponse,
|
426
|
-
} ),
|
427
|
-
...getMenuItemMocks( { GET: [] } ),
|
428
|
-
] );
|
429
|
-
|
413
|
+
it( 'saves menu name changes', async () => {
|
414
|
+
await createMenu( { name: initialMenuName } );
|
430
415
|
await visitNavigationEditor();
|
431
416
|
|
432
|
-
//
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
afterEach( async () => {
|
437
|
-
await setUpResponseMocking( [] );
|
438
|
-
} );
|
439
|
-
|
440
|
-
it( 'is displayed in inspector additions', async () => {
|
441
|
-
const nameControl = await page.$( nameEditorSelector );
|
442
|
-
expect( nameControl ).toBeDefined();
|
443
|
-
} );
|
444
|
-
|
445
|
-
it( 'saves menu name upon clicking save button', async () => {
|
446
|
-
const newName = 'newName';
|
447
|
-
const menuPostResponse = {
|
448
|
-
id: 4,
|
449
|
-
description: '',
|
450
|
-
name: newName,
|
451
|
-
slug: 'main-menu',
|
452
|
-
meta: [],
|
453
|
-
auto_add: false,
|
454
|
-
};
|
455
|
-
|
456
|
-
await setUpResponseMocking( [
|
457
|
-
...getMenuMocks( {
|
458
|
-
GET: [ menuPostResponse ],
|
459
|
-
POST: menuPostResponse,
|
460
|
-
} ),
|
461
|
-
...getMenuItemMocks( { GET: [] } ),
|
462
|
-
] );
|
463
|
-
|
464
|
-
// Ensure there is focus.
|
465
|
-
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 );
|
466
421
|
await pressKeyTimes( 'Backspace', initialMenuName.length );
|
467
422
|
await page.keyboard.type( newName );
|
468
|
-
|
469
|
-
const saveButton = await page.$(
|
470
|
-
'.edit-navigation-toolbar__save-button'
|
471
|
-
);
|
472
|
-
await saveButton.click();
|
423
|
+
await page.click( '.edit-navigation-toolbar__save-button' );
|
473
424
|
await page.waitForSelector( '.components-snackbar' );
|
425
|
+
await page.reload();
|
426
|
+
|
427
|
+
// Expect the header to have the new name.
|
474
428
|
const headerSubtitle = await page.waitForSelector(
|
475
|
-
'.edit-navigation-
|
429
|
+
'.edit-navigation-menu-actions__subtitle'
|
476
430
|
);
|
477
|
-
expect( headerSubtitle ).toBeTruthy();
|
478
431
|
const headerSubtitleText = await headerSubtitle.evaluate(
|
479
432
|
( element ) => element.innerText
|
480
433
|
);
|
481
|
-
expect( headerSubtitleText ).toBe(
|
434
|
+
expect( headerSubtitleText ).toBe( newName );
|
482
435
|
} );
|
483
436
|
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
name: initialMenuName,
|
489
|
-
slug: 'main-menu',
|
490
|
-
meta: [],
|
491
|
-
auto_add: false,
|
492
|
-
};
|
493
|
-
|
494
|
-
await setUpResponseMocking( [
|
495
|
-
...getMenuMocks( {
|
496
|
-
GET: [ menuPostResponse ],
|
497
|
-
POST: menuPostResponse,
|
498
|
-
} ),
|
499
|
-
...getMenuItemMocks( { GET: [] } ),
|
500
|
-
] );
|
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();
|
501
441
|
|
502
|
-
//
|
503
|
-
await page.
|
442
|
+
// Try saving a menu with an empty name.
|
443
|
+
await page.waitForSelector( inputSelector );
|
444
|
+
await page.click( inputSelector );
|
504
445
|
await pressKeyTimes( 'Backspace', initialMenuName.length );
|
505
|
-
|
506
|
-
const
|
507
|
-
'.
|
446
|
+
await page.click( '.edit-navigation-toolbar__save-button' );
|
447
|
+
const snackbar = await page.waitForSelector(
|
448
|
+
'.components-snackbar',
|
449
|
+
{ visible: true }
|
508
450
|
);
|
509
|
-
await
|
510
|
-
|
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.
|
511
463
|
const headerSubtitle = await page.waitForSelector(
|
512
|
-
'.edit-navigation-
|
464
|
+
'.edit-navigation-menu-actions__subtitle'
|
513
465
|
);
|
514
|
-
expect( headerSubtitle ).toBeTruthy();
|
515
466
|
const headerSubtitleText = await headerSubtitle.evaluate(
|
516
467
|
( element ) => element.innerText
|
517
468
|
);
|
518
|
-
expect( headerSubtitleText ).toBe(
|
519
|
-
`Editing: ${ initialMenuName }`
|
520
|
-
);
|
469
|
+
expect( headerSubtitleText ).toBe( initialMenuName );
|
521
470
|
} );
|
522
471
|
} );
|
523
472
|
|
524
473
|
describe( 'Change detections', () => {
|
525
474
|
beforeEach( async () => {
|
526
|
-
|
527
|
-
id: 4,
|
528
|
-
description: '',
|
529
|
-
name: 'Main',
|
530
|
-
slug: 'main-menu',
|
531
|
-
meta: [],
|
532
|
-
auto_add: false,
|
533
|
-
};
|
534
|
-
|
535
|
-
await setUpResponseMocking( [
|
536
|
-
...getMenuMocks( {
|
537
|
-
GET: [ menuPostResponse ],
|
538
|
-
POST: menuPostResponse,
|
539
|
-
} ),
|
540
|
-
...getMenuItemMocks( { GET: [] } ),
|
541
|
-
] );
|
542
|
-
|
475
|
+
await createMenu( { name: 'Main' } );
|
543
476
|
await visitNavigationEditor();
|
544
477
|
} );
|
545
478
|
|
546
|
-
afterEach( async () => {
|
547
|
-
await setUpResponseMocking( [] );
|
548
|
-
} );
|
549
|
-
|
550
479
|
async function assertIsDirty( isDirty ) {
|
551
480
|
let hadDialog = false;
|
552
481
|
|
@@ -567,10 +496,12 @@ describe( 'Navigation editor', () => {
|
|
567
496
|
}
|
568
497
|
}
|
569
498
|
|
499
|
+
// eslint-disable-next-line jest/no-disabled-tests
|
570
500
|
it.skip( 'should not prompt to confirm unsaved changes for the newly selected menu', async () => {
|
571
501
|
await assertIsDirty( false );
|
572
502
|
} );
|
573
503
|
|
504
|
+
// eslint-disable-next-line jest/no-disabled-tests
|
574
505
|
it.skip( 'should prompt to confirm unsaved changes when menu name is edited', async () => {
|
575
506
|
await page.type(
|
576
507
|
'.edit-navigation-name-editor__text-control input',
|
@@ -580,4 +511,172 @@ describe( 'Navigation editor', () => {
|
|
580
511
|
await assertIsDirty( true );
|
581
512
|
} );
|
582
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
|
+
} );
|
583
682
|
} );
|