@wordpress/e2e-tests 3.0.1-next.33ec3857e2.0 → 3.0.4
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 +2 -1
- package/LICENSE.md +1 -1
- package/README.md +31 -19
- package/config/is-gutenberg-plugin.js +6 -0
- package/jest.config.js +1 -1
- package/jest.performance.config.js +1 -1
- package/mu-plugins/enable-templates-ui.php +24 -0
- package/package.json +9 -9
- package/plugins/plugins-api/error-boundary.js +11 -0
- package/plugins/plugins-error-boundary.php +27 -0
- package/plugins/query-block.php +2 -2
- package/specs/editor/blocks/__snapshots__/image.test.js.snap +6 -6
- package/specs/editor/blocks/__snapshots__/navigation.test.js.snap +4 -2
- package/specs/editor/blocks/__snapshots__/spacer.test.js.snap +1 -1
- package/specs/editor/blocks/classic.test.js +5 -2
- package/specs/editor/blocks/cover.test.js +7 -3
- package/specs/editor/blocks/gallery.test.js +6 -1
- package/specs/editor/blocks/heading.test.js +1 -11
- package/specs/editor/blocks/navigation.test.js +279 -240
- package/specs/editor/plugins/__snapshots__/plugins-api.test.js.snap +2 -2
- package/specs/editor/plugins/block-variations.test.js +3 -3
- package/specs/editor/plugins/iframed-inline-styles.test.js +0 -6
- package/specs/editor/plugins/iframed-multiple-block-stylesheets.test.js +0 -4
- package/specs/editor/plugins/plugins-api.test.js +30 -0
- package/specs/editor/plugins/templates.test.js +1 -7
- package/specs/editor/various/__snapshots__/block-editor-keyboard-shortcuts.test.js.snap +38 -24
- package/specs/editor/various/__snapshots__/inserting-blocks.test.js.snap +1 -1
- package/specs/editor/various/__snapshots__/keep-styles-on-block-transforms.test.js.snap +35 -0
- package/specs/editor/various/block-editor-keyboard-shortcuts.test.js +43 -3
- package/specs/editor/various/font-size-picker.test.js +57 -11
- package/specs/editor/various/fullscreen-mode.test.js +1 -1
- package/specs/editor/various/keep-styles-on-block-transforms.test.js +81 -0
- package/specs/editor/various/post-editor-template-mode.test.js +1 -1
- package/specs/editor/various/post-visibility.test.js +54 -0
- package/specs/editor/various/preview.test.js +66 -1
- package/specs/editor/various/reusable-blocks.test.js +52 -5
- package/specs/editor/various/style-variation.test.js +9 -5
- package/specs/editor/various/undo.test.js +21 -0
- package/specs/performance/site-editor.test.js +3 -4
- package/specs/site-editor/document-settings.test.js +12 -14
- package/specs/site-editor/multi-entity-editing.test.js +14 -16
- package/specs/site-editor/multi-entity-saving.test.js +18 -27
- package/specs/site-editor/settings-sidebar.test.js +7 -12
- package/specs/site-editor/site-editor-export.test.js +9 -10
- package/specs/site-editor/site-editor-inserter.test.js +7 -9
- package/specs/site-editor/style-variations.test.js +211 -0
- package/specs/site-editor/template-part.test.js +14 -22
- package/specs/site-editor/template-revert.test.js +31 -37
- package/specs/widgets/customizing-widgets.test.js +3 -23
- package/specs/widgets/editing-widgets.test.js +36 -12
- package/themes/style-variations/block-templates/index.html +11 -0
- package/themes/style-variations/index.php +0 -0
- package/themes/style-variations/style.css +15 -0
- package/themes/style-variations/styles/pink.json +33 -0
- package/themes/style-variations/styles/yellow.json +12 -0
- package/themes/style-variations/theme.json +8 -0
- package/config/gutenberg-phase.js +0 -9
- package/specs/editor/various/__snapshots__/style-variation.test.js.snap +0 -7
- package/specs/site-editor/utils.js +0 -153
@@ -1,7 +1,14 @@
|
|
1
|
+
/**
|
2
|
+
* External dependencies
|
3
|
+
*/
|
4
|
+
import { uniqueId } from 'lodash';
|
5
|
+
|
1
6
|
/**
|
2
7
|
* WordPress dependencies
|
3
8
|
*/
|
4
9
|
import {
|
10
|
+
clickButton,
|
11
|
+
clickOnMoreMenuItem,
|
5
12
|
createJSONResponse,
|
6
13
|
createNewPost,
|
7
14
|
createMenu as createClassicMenu,
|
@@ -12,12 +19,15 @@ import {
|
|
12
19
|
saveDraft,
|
13
20
|
showBlockToolbar,
|
14
21
|
openPreviewPage,
|
15
|
-
selectBlockByClientId,
|
16
|
-
getAllBlocks,
|
17
22
|
ensureSidebarOpened,
|
18
23
|
__experimentalRest as rest,
|
19
24
|
publishPost,
|
25
|
+
createUser,
|
26
|
+
loginUser,
|
27
|
+
deleteUser,
|
28
|
+
switchUserToAdmin,
|
20
29
|
} from '@wordpress/e2e-test-utils';
|
30
|
+
import { addQueryArgs } from '@wordpress/url';
|
21
31
|
|
22
32
|
/**
|
23
33
|
* Internal dependencies
|
@@ -26,6 +36,7 @@ import menuItemsFixture from '../fixtures/menu-items-request-fixture.json';
|
|
26
36
|
|
27
37
|
const POSTS_ENDPOINT = '/wp/v2/posts';
|
28
38
|
const PAGES_ENDPOINT = '/wp/v2/pages';
|
39
|
+
const DRAFT_PAGES_ENDPOINT = [ PAGES_ENDPOINT, { status: 'draft' } ];
|
29
40
|
const NAVIGATION_MENUS_ENDPOINT = '/wp/v2/navigation';
|
30
41
|
|
31
42
|
async function mockSearchResponse( items ) {
|
@@ -63,7 +74,10 @@ async function updateActiveNavigationLink( { url, label, type } ) {
|
|
63
74
|
};
|
64
75
|
|
65
76
|
if ( url ) {
|
66
|
-
await page.
|
77
|
+
const input = await page.waitForSelector(
|
78
|
+
'input[placeholder="Search or type url"]'
|
79
|
+
);
|
80
|
+
await input.type( url );
|
67
81
|
|
68
82
|
const suggestionPath = `//button[contains(@class, 'block-editor-link-control__search-item') and contains(@class, '${ typeClasses[ type ] }')]/span/span[@class='block-editor-link-control__search-item-title']/mark[text()="${ url }"]`;
|
69
83
|
|
@@ -110,22 +124,7 @@ async function selectClassicMenu( optionText ) {
|
|
110
124
|
const PLACEHOLDER_ACTIONS_CLASS = 'wp-block-navigation-placeholder__actions';
|
111
125
|
const PLACEHOLDER_ACTIONS_XPATH = `//*[contains(@class, '${ PLACEHOLDER_ACTIONS_CLASS }')]`;
|
112
126
|
const START_EMPTY_XPATH = `${ PLACEHOLDER_ACTIONS_XPATH }//button[text()='Start empty']`;
|
113
|
-
const
|
114
|
-
|
115
|
-
async function turnResponsivenessOn() {
|
116
|
-
const blocks = await getAllBlocks();
|
117
|
-
|
118
|
-
await selectBlockByClientId( blocks[ 0 ].clientId );
|
119
|
-
await ensureSidebarOpened();
|
120
|
-
|
121
|
-
const [ responsivenessToggleButton ] = await page.$x(
|
122
|
-
'//label[text()[contains(.,"Enable responsive menu")]]'
|
123
|
-
);
|
124
|
-
|
125
|
-
await responsivenessToggleButton.click();
|
126
|
-
|
127
|
-
await saveDraft();
|
128
|
-
}
|
127
|
+
const SELECT_MENU_XPATH = `${ PLACEHOLDER_ACTIONS_XPATH }//button[text()='Select menu']`;
|
129
128
|
|
130
129
|
/**
|
131
130
|
* Delete all items for the given REST resources using the REST API.
|
@@ -133,8 +132,17 @@ async function turnResponsivenessOn() {
|
|
133
132
|
* @param {*} endpoints The endpoints of the resources to delete.
|
134
133
|
*/
|
135
134
|
async function deleteAll( endpoints ) {
|
136
|
-
for ( const
|
137
|
-
const
|
135
|
+
for ( const endpoint of endpoints ) {
|
136
|
+
const defaultArgs = { per_page: -1 };
|
137
|
+
const isArrayEndpoint = Array.isArray( endpoint );
|
138
|
+
const path = isArrayEndpoint ? endpoint[ 0 ] : endpoint;
|
139
|
+
const args = isArrayEndpoint
|
140
|
+
? { ...defaultArgs, ...endpoint[ 1 ] }
|
141
|
+
: defaultArgs;
|
142
|
+
|
143
|
+
const items = await rest( {
|
144
|
+
path: addQueryArgs( path, args ),
|
145
|
+
} );
|
138
146
|
|
139
147
|
for ( const item of items ) {
|
140
148
|
await rest( {
|
@@ -145,24 +153,6 @@ async function deleteAll( endpoints ) {
|
|
145
153
|
}
|
146
154
|
}
|
147
155
|
|
148
|
-
/**
|
149
|
-
* Create a set of pages using the REST API.
|
150
|
-
*
|
151
|
-
* @param {Array} pages An array of page objects.
|
152
|
-
*/
|
153
|
-
async function createPages( pages ) {
|
154
|
-
for ( const page of pages ) {
|
155
|
-
await rest( {
|
156
|
-
method: 'POST',
|
157
|
-
path: PAGES_ENDPOINT,
|
158
|
-
data: {
|
159
|
-
status: 'publish',
|
160
|
-
...page,
|
161
|
-
},
|
162
|
-
} );
|
163
|
-
}
|
164
|
-
}
|
165
|
-
|
166
156
|
/**
|
167
157
|
* Replace unique ids in nav block content, since these won't be consistent
|
168
158
|
* between test runs.
|
@@ -192,6 +182,10 @@ async function getNavigationMenuRawContent() {
|
|
192
182
|
return navigationBlock.attributes.ref;
|
193
183
|
} );
|
194
184
|
|
185
|
+
if ( ! menuRef ) {
|
186
|
+
throw 'getNavigationMenuRawContent was unable to find a ref attribute on the first navigation block';
|
187
|
+
}
|
188
|
+
|
195
189
|
const response = await rest( {
|
196
190
|
method: 'GET',
|
197
191
|
path: `/wp/v2/navigation/${ menuRef }?context=edit`,
|
@@ -203,10 +197,23 @@ async function getNavigationMenuRawContent() {
|
|
203
197
|
// Disable reason - these tests are to be re-written.
|
204
198
|
// eslint-disable-next-line jest/no-disabled-tests
|
205
199
|
describe( 'Navigation', () => {
|
200
|
+
const contributorUsername = uniqueId( 'contributoruser_' );
|
201
|
+
let contributorPassword;
|
202
|
+
|
203
|
+
beforeAll( async () => {
|
204
|
+
// Creation of the contributor user **MUST** be at the top level describe block
|
205
|
+
// otherwise this test will become unstable. This action only happens once
|
206
|
+
// so there is no huge performance hit.
|
207
|
+
contributorPassword = await createUser( contributorUsername, {
|
208
|
+
role: 'contributor',
|
209
|
+
} );
|
210
|
+
} );
|
211
|
+
|
206
212
|
beforeEach( async () => {
|
207
213
|
await deleteAll( [
|
208
214
|
POSTS_ENDPOINT,
|
209
215
|
PAGES_ENDPOINT,
|
216
|
+
DRAFT_PAGES_ENDPOINT,
|
210
217
|
NAVIGATION_MENUS_ENDPOINT,
|
211
218
|
] );
|
212
219
|
await deleteAllClassicMenus();
|
@@ -220,43 +227,17 @@ describe( 'Navigation', () => {
|
|
220
227
|
await deleteAll( [
|
221
228
|
POSTS_ENDPOINT,
|
222
229
|
PAGES_ENDPOINT,
|
230
|
+
DRAFT_PAGES_ENDPOINT,
|
223
231
|
NAVIGATION_MENUS_ENDPOINT,
|
224
232
|
] );
|
225
233
|
await deleteAllClassicMenus();
|
234
|
+
|
235
|
+
// As per the creation in the beforeAll() above, this
|
236
|
+
// action must be done at the root level describe() block.
|
237
|
+
await deleteUser( contributorUsername );
|
226
238
|
} );
|
227
239
|
|
228
240
|
describe( 'placeholder', () => {
|
229
|
-
it( 'allows a navigation block to be created using existing pages', async () => {
|
230
|
-
await createPages( [
|
231
|
-
{
|
232
|
-
title: 'About',
|
233
|
-
menu_order: 0,
|
234
|
-
},
|
235
|
-
{
|
236
|
-
title: 'Contact Us',
|
237
|
-
menu_order: 1,
|
238
|
-
},
|
239
|
-
{
|
240
|
-
title: 'FAQ',
|
241
|
-
menu_order: 2,
|
242
|
-
},
|
243
|
-
] );
|
244
|
-
|
245
|
-
await createNewPost();
|
246
|
-
|
247
|
-
// Add the navigation block.
|
248
|
-
await insertBlock( 'Navigation' );
|
249
|
-
const allPagesButton = await page.waitForXPath(
|
250
|
-
ADD_ALL_PAGES_XPATH
|
251
|
-
);
|
252
|
-
await allPagesButton.click();
|
253
|
-
|
254
|
-
// Wait for the page list block to be present
|
255
|
-
await page.waitForSelector( 'div[aria-label="Block: Page List"]' );
|
256
|
-
|
257
|
-
expect( await getNavigationMenuRawContent() ).toMatchSnapshot();
|
258
|
-
} );
|
259
|
-
|
260
241
|
it( 'allows a navigation block to be created from existing menus', async () => {
|
261
242
|
await createClassicMenu( { name: 'Test Menu 1' } );
|
262
243
|
await createClassicMenu(
|
@@ -438,52 +419,53 @@ describe( 'Navigation', () => {
|
|
438
419
|
expect( await getNavigationMenuRawContent() ).toMatchSnapshot();
|
439
420
|
} );
|
440
421
|
|
441
|
-
|
442
|
-
it.skip( 'allows pages to be created from the navigation block and their links added to menu', async () => {
|
422
|
+
it( 'allows pages to be created from the navigation block and their links added to menu', async () => {
|
443
423
|
await createNewPost();
|
444
424
|
await insertBlock( 'Navigation' );
|
445
425
|
const startEmptyButton = await page.waitForXPath( START_EMPTY_XPATH );
|
446
426
|
await startEmptyButton.click();
|
447
|
-
|
448
427
|
const appender = await page.waitForSelector(
|
449
428
|
'.wp-block-navigation .block-list-appender'
|
450
429
|
);
|
451
430
|
await appender.click();
|
452
431
|
|
453
432
|
// Wait for URL input to be focused
|
454
|
-
await page.waitForSelector(
|
455
|
-
'input.block-editor-url-input__input:focus'
|
456
|
-
);
|
457
|
-
|
458
433
|
// Insert name for the new page.
|
459
|
-
|
460
|
-
|
461
|
-
'A really long page name that will not exist'
|
462
|
-
);
|
463
|
-
|
464
|
-
// Wait for URL input to be focused
|
465
|
-
await page.waitForSelector(
|
434
|
+
const pageTitle = 'A really long page name that will not exist';
|
435
|
+
const input = await page.waitForSelector(
|
466
436
|
'input.block-editor-url-input__input:focus'
|
467
437
|
);
|
468
|
-
|
469
|
-
|
470
|
-
|
438
|
+
await input.type( pageTitle );
|
439
|
+
|
440
|
+
// When creating a page, the URLControl makes a request to the
|
441
|
+
// url-details endpoint to fetch information about the page.
|
442
|
+
// Because the draft is inaccessible publicly, this request
|
443
|
+
// returns a 404 response. Wait for the response and expect
|
444
|
+
// the error to have occurred.
|
445
|
+
const createPageButton = await page.waitForSelector(
|
471
446
|
'.block-editor-link-control__search-create'
|
472
447
|
);
|
473
|
-
|
474
|
-
|
475
|
-
|
448
|
+
const responsePromise = page.waitForResponse(
|
449
|
+
( response ) =>
|
450
|
+
response.url().includes( 'url-details' ) &&
|
451
|
+
response.status() === 404
|
476
452
|
);
|
453
|
+
const createPagePromise = createPageButton.click();
|
454
|
+
await Promise.all( [ responsePromise, createPagePromise ] );
|
477
455
|
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
456
|
+
// Creating a draft is async, so wait for a sign of completion. In this
|
457
|
+
// case the link that shows in the URL popover once a link is added.
|
458
|
+
await page.waitForXPath(
|
459
|
+
`//a[contains(@class, "block-editor-link-control__search-item-title") and contains(., "${ pageTitle }")]`
|
482
460
|
);
|
483
|
-
|
461
|
+
|
462
|
+
await publishPost();
|
484
463
|
|
485
464
|
// Expect a Navigation Block with a link for "A really long page name that will not exist".
|
486
465
|
expect( await getNavigationMenuRawContent() ).toMatchSnapshot();
|
466
|
+
expect( console ).toHaveErroredWith(
|
467
|
+
'Failed to load resource: the server responded with a status of 404 (Not Found)'
|
468
|
+
);
|
487
469
|
} );
|
488
470
|
|
489
471
|
it( 'renders buttons for the submenu opener elements when the block is set to open on click instead of hover', async () => {
|
@@ -564,125 +546,41 @@ describe( 'Navigation', () => {
|
|
564
546
|
expect( quickInserter ).toBeTruthy();
|
565
547
|
} );
|
566
548
|
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
// {
|
574
|
-
// title: 'Home',
|
575
|
-
// slug: 'home',
|
576
|
-
// },
|
577
|
-
// {
|
578
|
-
// title: 'About',
|
579
|
-
// slug: 'about',
|
580
|
-
// },
|
581
|
-
// {
|
582
|
-
// title: 'Contact Us',
|
583
|
-
// slug: 'contact',
|
584
|
-
// },
|
585
|
-
// ] );
|
586
|
-
|
587
|
-
// Create first block at the start in order to enable preview.
|
588
|
-
await insertBlock( 'Navigation' );
|
589
|
-
await saveDraft();
|
590
|
-
|
591
|
-
const previewPage = await openPreviewPage();
|
592
|
-
const isScriptLoaded = await previewPage.evaluate(
|
593
|
-
() =>
|
594
|
-
null !==
|
595
|
-
document.querySelector(
|
596
|
-
'script[src*="navigation/view.min.js"]'
|
597
|
-
)
|
549
|
+
it( 'supports navigation blocks that have inner blocks within their markup and converts them to wp_navigation posts', async () => {
|
550
|
+
// Insert 'old-school' inner blocks via the code editor.
|
551
|
+
await createNewPost();
|
552
|
+
await clickOnMoreMenuItem( 'Code editor' );
|
553
|
+
const codeEditorInput = await page.waitForSelector(
|
554
|
+
'.editor-post-text-editor'
|
598
555
|
);
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
await
|
604
|
-
await
|
605
|
-
|
606
|
-
await allPagesButton2.click();
|
607
|
-
await turnResponsivenessOn();
|
608
|
-
|
609
|
-
await previewPage.reload( {
|
610
|
-
waitFor: [ 'networkidle0', 'domcontentloaded' ],
|
611
|
-
} );
|
612
|
-
|
613
|
-
/*
|
614
|
-
Count instances of the tag to make sure that it's been loaded only once,
|
615
|
-
regardless of the number of navigation blocks present.
|
616
|
-
*/
|
617
|
-
const tagCount = await previewPage.evaluate(
|
618
|
-
() =>
|
619
|
-
Array.from(
|
620
|
-
document.querySelectorAll(
|
621
|
-
'script[src*="navigation/view.min.js"]'
|
622
|
-
)
|
623
|
-
).length
|
556
|
+
await codeEditorInput.click();
|
557
|
+
const markup =
|
558
|
+
'<!-- wp:navigation --><!-- wp:page-list /--><!-- /wp:navigation -->';
|
559
|
+
await page.keyboard.type( markup );
|
560
|
+
await clickButton( 'Exit code editor' );
|
561
|
+
const navBlock = await page.waitForSelector(
|
562
|
+
'nav[aria-label="Block: Navigation"]'
|
624
563
|
);
|
564
|
+
// Select the block to convert to a wp_navigation and publish.
|
565
|
+
// The select menu button shows up when saving is complete.
|
566
|
+
await navBlock.click();
|
567
|
+
await page.waitForSelector( 'button[aria-label="Select Menu"]' );
|
568
|
+
await publishPost();
|
625
569
|
|
626
|
-
|
570
|
+
// Check that the wp_navigation post has the page list block.
|
571
|
+
expect( await getNavigationMenuRawContent() ).toMatchSnapshot();
|
627
572
|
} );
|
628
573
|
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
// title: 'Home',
|
633
|
-
// slug: 'home',
|
634
|
-
// },
|
635
|
-
// {
|
636
|
-
// title: 'About',
|
637
|
-
// slug: 'about',
|
638
|
-
// },
|
639
|
-
// {
|
640
|
-
// title: 'Contact Us',
|
641
|
-
// slug: 'contact',
|
642
|
-
// },
|
643
|
-
// ] );
|
644
|
-
|
645
|
-
await insertBlock( 'Navigation' );
|
646
|
-
await saveDraft();
|
647
|
-
|
648
|
-
const previewPage = await openPreviewPage();
|
649
|
-
let isScriptLoaded = await previewPage.evaluate(
|
650
|
-
() =>
|
651
|
-
null !==
|
652
|
-
document.querySelector(
|
653
|
-
'script[src*="navigation/view.min.js"]'
|
654
|
-
)
|
655
|
-
);
|
656
|
-
|
657
|
-
expect( isScriptLoaded ).toBe( false );
|
658
|
-
|
659
|
-
const allPagesButton = await page.waitForXPath( ADD_ALL_PAGES_XPATH );
|
660
|
-
await allPagesButton.click();
|
574
|
+
describe( 'Creating and restarting', () => {
|
575
|
+
const NAV_ENTITY_SELECTOR =
|
576
|
+
'//div[@class="entities-saved-states__panel"]//label//strong[contains(text(), "Navigation")]';
|
661
577
|
|
662
|
-
await turnResponsivenessOn();
|
663
|
-
|
664
|
-
await previewPage.reload( {
|
665
|
-
waitFor: [ 'networkidle0', 'domcontentloaded' ],
|
666
|
-
} );
|
667
|
-
|
668
|
-
isScriptLoaded = await previewPage.evaluate(
|
669
|
-
() =>
|
670
|
-
null !==
|
671
|
-
document.querySelector(
|
672
|
-
'script[src*="navigation/view.min.js"]'
|
673
|
-
)
|
674
|
-
);
|
675
|
-
|
676
|
-
expect( isScriptLoaded ).toBe( true );
|
677
|
-
} );
|
678
|
-
|
679
|
-
describe.skip( 'Creating and restarting', () => {
|
680
578
|
async function populateNavWithOneItem() {
|
681
579
|
// Add a Link block first.
|
682
|
-
await page.waitForSelector(
|
580
|
+
const appender = await page.waitForSelector(
|
683
581
|
'.wp-block-navigation .block-list-appender'
|
684
582
|
);
|
685
|
-
await
|
583
|
+
await appender.click();
|
686
584
|
// Add a link to the Link block.
|
687
585
|
await updateActiveNavigationLink( {
|
688
586
|
url: 'https://wordpress.org',
|
@@ -692,62 +590,88 @@ describe( 'Navigation', () => {
|
|
692
590
|
}
|
693
591
|
|
694
592
|
async function resetNavBlockToInitialState() {
|
695
|
-
await page.waitForSelector(
|
696
|
-
|
697
|
-
|
698
|
-
await
|
699
|
-
const newMenuButton = await page
|
593
|
+
const selectMenuDropdown = await page.waitForSelector(
|
594
|
+
'[aria-label="Select Menu"]'
|
595
|
+
);
|
596
|
+
await selectMenuDropdown.click();
|
597
|
+
const newMenuButton = await page.waitForXPath(
|
700
598
|
'//span[text()="Create new menu"]'
|
701
599
|
);
|
702
|
-
newMenuButton
|
600
|
+
newMenuButton.click();
|
703
601
|
}
|
704
602
|
|
705
|
-
it( '
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
//
|
721
|
-
//
|
603
|
+
it( 'does not retain uncontrolled inner blocks when creating a new entity', async () => {
|
604
|
+
await createNewPost();
|
605
|
+
await clickOnMoreMenuItem( 'Code editor' );
|
606
|
+
const codeEditorInput = await page.waitForSelector(
|
607
|
+
'.editor-post-text-editor'
|
608
|
+
);
|
609
|
+
await codeEditorInput.click();
|
610
|
+
const markup =
|
611
|
+
'<!-- wp:navigation --><!-- wp:page-list /--><!-- /wp:navigation -->';
|
612
|
+
await page.keyboard.type( markup );
|
613
|
+
await clickButton( 'Exit code editor' );
|
614
|
+
const navBlock = await page.waitForSelector(
|
615
|
+
'nav[aria-label="Block: Navigation"]'
|
616
|
+
);
|
617
|
+
|
618
|
+
// Select the block to convert to a wp_navigation and publish.
|
619
|
+
// The select menu button shows up when saving is complete.
|
620
|
+
await navBlock.click();
|
621
|
+
await page.waitForSelector( 'button[aria-label="Select Menu"]' );
|
622
|
+
|
623
|
+
// Reset the nav block to create a new entity.
|
624
|
+
await resetNavBlockToInitialState();
|
625
|
+
const startEmptyButton = await page.waitForXPath(
|
626
|
+
START_EMPTY_XPATH
|
627
|
+
);
|
628
|
+
await startEmptyButton.click();
|
629
|
+
await populateNavWithOneItem();
|
630
|
+
|
631
|
+
// Confirm that only the last menu entity was updated.
|
632
|
+
const publishPanelButton2 = await page.waitForSelector(
|
633
|
+
'.editor-post-publish-button__button:not([aria-disabled="true"])'
|
634
|
+
);
|
635
|
+
await publishPanelButton2.click();
|
636
|
+
|
637
|
+
await page.waitForXPath( NAV_ENTITY_SELECTOR );
|
638
|
+
expect( await page.$x( NAV_ENTITY_SELECTOR ) ).toHaveLength( 1 );
|
639
|
+
} );
|
722
640
|
|
641
|
+
it( 'only updates a single entity currently linked with the block', async () => {
|
642
|
+
await createNewPost();
|
723
643
|
await insertBlock( 'Navigation' );
|
644
|
+
|
724
645
|
const startEmptyButton = await page.waitForXPath(
|
725
646
|
START_EMPTY_XPATH
|
726
647
|
);
|
727
648
|
await startEmptyButton.click();
|
728
649
|
await populateNavWithOneItem();
|
729
650
|
|
730
|
-
//
|
731
|
-
await page.waitForSelector(
|
651
|
+
// Confirm that the menu entity was updated.
|
652
|
+
const publishPanelButton = await page.waitForSelector(
|
732
653
|
'.editor-post-publish-panel__toggle:not([aria-disabled="true"])'
|
733
654
|
);
|
734
|
-
await
|
655
|
+
await publishPanelButton.click();
|
735
656
|
|
736
|
-
const NAV_ENTITY_SELECTOR =
|
737
|
-
'//div[@class="entities-saved-states__panel"]//label//strong[contains(text(), "Navigation")]';
|
738
657
|
await page.waitForXPath( NAV_ENTITY_SELECTOR );
|
739
658
|
expect( await page.$x( NAV_ENTITY_SELECTOR ) ).toHaveLength( 1 );
|
740
659
|
|
741
660
|
// Publish the post
|
742
|
-
await page.
|
743
|
-
|
744
|
-
|
661
|
+
const entitySaveButton = await page.waitForSelector(
|
662
|
+
'.editor-entities-saved-states__save-button'
|
663
|
+
);
|
664
|
+
await entitySaveButton.click();
|
665
|
+
const publishButton = await page.waitForSelector(
|
666
|
+
'.editor-post-publish-button:not([aria-disabled="true"])'
|
667
|
+
);
|
668
|
+
await publishButton.click();
|
745
669
|
|
746
|
-
// A success notice should show up
|
670
|
+
// A success notice should show up.
|
747
671
|
await page.waitForSelector( '.components-snackbar' );
|
748
672
|
|
749
673
|
// Now try inserting another Link block via the quick inserter.
|
750
|
-
await page.
|
674
|
+
await page.click( 'nav[aria-label="Block: Navigation"]' );
|
751
675
|
|
752
676
|
await resetNavBlockToInitialState();
|
753
677
|
const startEmptyButton2 = await page.waitForXPath(
|
@@ -756,14 +680,129 @@ describe( 'Navigation', () => {
|
|
756
680
|
await startEmptyButton2.click();
|
757
681
|
await populateNavWithOneItem();
|
758
682
|
|
759
|
-
//
|
760
|
-
await page.waitForSelector(
|
683
|
+
// Confirm that only the last menu entity was updated.
|
684
|
+
const publishPanelButton2 = await page.waitForSelector(
|
761
685
|
'.editor-post-publish-button__button:not([aria-disabled="true"])'
|
762
686
|
);
|
763
|
-
await
|
687
|
+
await publishPanelButton2.click();
|
764
688
|
|
765
689
|
await page.waitForXPath( NAV_ENTITY_SELECTOR );
|
766
690
|
expect( await page.$x( NAV_ENTITY_SELECTOR ) ).toHaveLength( 1 );
|
767
691
|
} );
|
768
692
|
} );
|
693
|
+
|
694
|
+
it( 'does not load the frontend script if no navigation blocks are present', async () => {
|
695
|
+
await createNewPost();
|
696
|
+
await insertBlock( 'Paragraph' );
|
697
|
+
await page.waitForSelector( 'p[data-title="Paragraph"]:focus' );
|
698
|
+
await page.keyboard.type( 'Hello' );
|
699
|
+
|
700
|
+
const previewPage = await openPreviewPage();
|
701
|
+
await previewPage.bringToFront();
|
702
|
+
await previewPage.waitForNetworkIdle();
|
703
|
+
|
704
|
+
const isScriptLoaded = await previewPage.evaluate(
|
705
|
+
() =>
|
706
|
+
null !==
|
707
|
+
document.querySelector(
|
708
|
+
'script[src*="navigation/view.min.js"]'
|
709
|
+
)
|
710
|
+
);
|
711
|
+
|
712
|
+
expect( isScriptLoaded ).toBe( false );
|
713
|
+
} );
|
714
|
+
|
715
|
+
it( 'loads the frontend script only once even when multiple navigation blocks are present', async () => {
|
716
|
+
await createNewPost();
|
717
|
+
await insertBlock( 'Navigation' );
|
718
|
+
await insertBlock( 'Navigation' );
|
719
|
+
|
720
|
+
const previewPage = await openPreviewPage();
|
721
|
+
await previewPage.bringToFront();
|
722
|
+
await previewPage.waitForNetworkIdle();
|
723
|
+
|
724
|
+
const tagCount = await previewPage.evaluate(
|
725
|
+
() =>
|
726
|
+
document.querySelectorAll(
|
727
|
+
'script[src*="navigation/view.min.js"]'
|
728
|
+
).length
|
729
|
+
);
|
730
|
+
|
731
|
+
expect( tagCount ).toBe( 1 );
|
732
|
+
} );
|
733
|
+
|
734
|
+
describe( 'Permission based restrictions', () => {
|
735
|
+
afterEach( async () => {
|
736
|
+
await switchUserToAdmin();
|
737
|
+
} );
|
738
|
+
|
739
|
+
it( 'shows a warning if user does not have permission to edit or update navigation menus', async () => {
|
740
|
+
await createNewPost();
|
741
|
+
await insertBlock( 'Navigation' );
|
742
|
+
|
743
|
+
const startEmptyButton = await page.waitForXPath(
|
744
|
+
START_EMPTY_XPATH
|
745
|
+
);
|
746
|
+
|
747
|
+
// This creates an empty Navigation post type entity.
|
748
|
+
await startEmptyButton.click();
|
749
|
+
|
750
|
+
// Publishing the Post ensures the Navigation entity is saved.
|
751
|
+
// The Post itself is irrelevant.
|
752
|
+
await publishPost();
|
753
|
+
|
754
|
+
// Switch to a Contributor role user - they should not have
|
755
|
+
// permission to update Navigation menus.
|
756
|
+
await loginUser( contributorUsername, contributorPassword );
|
757
|
+
|
758
|
+
await createNewPost();
|
759
|
+
|
760
|
+
await insertBlock( 'Navigation' );
|
761
|
+
|
762
|
+
// Select the Navigation post created by the Admin early
|
763
|
+
// in the test.
|
764
|
+
const navigationPostCreatedByAdminName = 'Navigation';
|
765
|
+
const dropdown = await page.waitForXPath( SELECT_MENU_XPATH );
|
766
|
+
await dropdown.click();
|
767
|
+
const theOption = await page.waitForXPath(
|
768
|
+
`//*[contains(@class, 'components-menu-item__item')][ text()="${ navigationPostCreatedByAdminName }" ]`
|
769
|
+
);
|
770
|
+
await theOption.click();
|
771
|
+
|
772
|
+
// Make sure the snackbar error shows up
|
773
|
+
await page.waitForXPath(
|
774
|
+
`//*[contains(@class, 'components-snackbar__content')][ text()="You do not have permission to edit this Menu. Any changes made will not be saved." ]`
|
775
|
+
);
|
776
|
+
|
777
|
+
// Expect a console 403 for request to Navigation Areas for lower permission users.
|
778
|
+
// This is because reading requires the `edit_theme_options` capability
|
779
|
+
// which the Contributor level user does not have.
|
780
|
+
// See: https://github.com/WordPress/gutenberg/blob/4cedaf0c4abb0aeac4bfd4289d63e9889efe9733/lib/class-wp-rest-block-navigation-areas-controller.php#L81-L91.
|
781
|
+
// Todo: removed once Nav Areas are removed from the Gutenberg Plugin.
|
782
|
+
expect( console ).toHaveErrored();
|
783
|
+
} );
|
784
|
+
|
785
|
+
it( 'shows a warning if user does not have permission to create navigation menus', async () => {
|
786
|
+
const noticeText =
|
787
|
+
'You do not have permission to create Navigation Menus.';
|
788
|
+
// Switch to a Contributor role user - they should not have
|
789
|
+
// permission to update Navigations.
|
790
|
+
await loginUser( contributorUsername, contributorPassword );
|
791
|
+
|
792
|
+
await createNewPost();
|
793
|
+
await insertBlock( 'Navigation' );
|
794
|
+
|
795
|
+
// Make sure the snackbar error shows up
|
796
|
+
await page.waitForXPath(
|
797
|
+
`//*[contains(@class, 'components-snackbar__content')][ text()="${ noticeText }" ]`
|
798
|
+
);
|
799
|
+
|
800
|
+
// Expect a console 403 for request to Navigation Areas for lower permission users.
|
801
|
+
// This is because reading requires the `edit_theme_options` capability
|
802
|
+
// which the Contributor level user does not have.
|
803
|
+
// See: https://github.com/WordPress/gutenberg/blob/4cedaf0c4abb0aeac4bfd4289d63e9889efe9733/lib/class-wp-rest-block-navigation-areas-controller.php#L81-L91.
|
804
|
+
// Todo: removed once Nav Areas are removed from the Gutenberg Plugin.
|
805
|
+
expect( console ).toHaveErrored();
|
806
|
+
} );
|
807
|
+
} );
|
769
808
|
} );
|