@wordpress/e2e-tests 2.5.9 → 3.0.1-next.33ec3857e2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/config/flaky-tests-reporter.js +2 -1
  3. package/package.json +10 -9
  4. package/specs/editor/blocks/__snapshots__/heading.test.js.snap +2 -2
  5. package/specs/editor/blocks/__snapshots__/navigation.test.js.snap +27 -59
  6. package/specs/editor/blocks/columns.test.js +1 -1
  7. package/specs/editor/blocks/cover.test.js +4 -1
  8. package/specs/editor/blocks/heading.test.js +15 -3
  9. package/specs/editor/blocks/image.test.js +15 -11
  10. package/specs/editor/blocks/navigation.test.js +264 -370
  11. package/specs/editor/blocks/preformatted.test.js +2 -1
  12. package/specs/editor/blocks/site-title.test.js +2 -31
  13. package/specs/editor/fixtures/menu-items-request-fixture.json +84 -0
  14. package/specs/editor/fixtures/menu-items-response-fixture.json +240 -144
  15. package/specs/editor/plugins/custom-post-types.test.js +4 -3
  16. package/specs/editor/various/adding-patterns.test.js +1 -1
  17. package/specs/editor/various/block-grouping.test.js +30 -0
  18. package/specs/editor/various/block-hierarchy-navigation.test.js +3 -3
  19. package/specs/editor/various/change-detection.test.js +5 -0
  20. package/specs/editor/various/editor-modes.test.js +7 -0
  21. package/specs/editor/various/font-size-picker.test.js +1 -7
  22. package/specs/editor/various/format-library/__snapshots__/text-color.test.js.snap +13 -0
  23. package/specs/editor/various/format-library/text-color.test.js +46 -0
  24. package/specs/editor/various/inserting-blocks.test.js +6 -2
  25. package/specs/editor/various/keyboard-navigable-blocks.test.js +6 -0
  26. package/specs/editor/various/list-view.test.js +2 -2
  27. package/specs/editor/various/navigable-toolbar.test.js +2 -2
  28. package/specs/editor/various/preview.test.js +1 -1
  29. package/specs/editor/various/reusable-blocks.test.js +1 -26
  30. package/specs/editor/various/writing-flow.test.js +8 -4
  31. package/specs/site-editor/document-settings.test.js +6 -6
  32. package/specs/site-editor/multi-entity-saving.test.js +108 -55
  33. package/specs/site-editor/settings-sidebar.test.js +2 -3
  34. package/specs/site-editor/template-part.test.js +88 -68
  35. package/specs/widgets/customizing-widgets.test.js +4 -0
@@ -4,11 +4,14 @@
4
4
  import {
5
5
  createNewPost,
6
6
  disablePrePublishChecks,
7
+ getOption,
7
8
  insertBlock,
8
9
  publishPost,
10
+ setOption,
9
11
  trashAllPosts,
10
12
  activateTheme,
11
13
  clickButton,
14
+ createReusableBlock,
12
15
  } from '@wordpress/e2e-test-utils';
13
16
 
14
17
  /**
@@ -21,13 +24,9 @@ describe( 'Multi-entity save flow', () => {
21
24
  const checkedBoxSelector = '.components-checkbox-control__checked';
22
25
  const checkboxInputSelector = '.components-checkbox-control__input';
23
26
  const entitiesSaveSelector = '.editor-entities-saved-states__save-button';
24
- const templatePartSelector = '*[data-type="core/template-part"]';
25
- const activatedTemplatePartSelector = `${ templatePartSelector }.block-editor-block-list__layout`;
26
27
  const savePanelSelector = '.entities-saved-states__panel';
27
28
  const closePanelButtonSelector =
28
- '.editor-post-publish-panel__header-cancel-button button';
29
- const createNewButtonSelector =
30
- '//button[contains(text(), "New template part")]';
29
+ '.editor-post-publish-panel__header-cancel-button button:not(:disabled)';
31
30
 
32
31
  // Reusable assertions across Post/Site editors.
33
32
  const assertAllBoxesChecked = async () => {
@@ -44,14 +43,26 @@ describe( 'Multi-entity save flow', () => {
44
43
  }
45
44
  };
46
45
 
46
+ let originalSiteTitle, originalBlogDescription;
47
+
47
48
  beforeAll( async () => {
48
49
  await activateTheme( 'tt1-blocks' );
49
50
  await trashAllPosts( 'wp_template' );
50
51
  await trashAllPosts( 'wp_template_part' );
52
+ await trashAllPosts( 'wp_block' );
53
+
54
+ // Get the current Site Title and Site Tagline, so that we can reset
55
+ // them back to the original values once the test suite has finished.
56
+ originalSiteTitle = await getOption( 'blogname' );
57
+ originalBlogDescription = await getOption( 'blogdescription' );
51
58
  } );
52
59
 
53
60
  afterAll( async () => {
54
61
  await activateTheme( 'twentytwentyone' );
62
+
63
+ // Reset the Site Title and Site Tagline back to their original values.
64
+ await setOption( 'blogname', originalSiteTitle );
65
+ await setOption( 'blogdescription', originalBlogDescription );
55
66
  } );
56
67
 
57
68
  describe( 'Post Editor', () => {
@@ -66,8 +77,6 @@ describe( 'Multi-entity save flow', () => {
66
77
  const saveA11ySelector =
67
78
  '.edit-post-layout__toggle-entities-saved-states-panel-button';
68
79
  const publishPanelSelector = '.editor-post-publish-panel';
69
- const confirmTitleButtonSelector =
70
- '.wp-block-template-part__placeholder-create-new__title-form .components-button.is-primary';
71
80
 
72
81
  // Reusable assertions inside Post editor.
73
82
  const assertMultiSaveEnabled = async () => {
@@ -87,6 +96,7 @@ describe( 'Multi-entity save flow', () => {
87
96
  it( 'Save flow should work as expected.', async () => {
88
97
  await createNewPost();
89
98
  // Edit the page some.
99
+ await page.waitForSelector( '.editor-post-title' );
90
100
  await page.click( '.editor-post-title' );
91
101
  await page.keyboard.type( 'Test Post...' );
92
102
  await page.keyboard.press( 'Enter' );
@@ -100,21 +110,11 @@ describe( 'Multi-entity save flow', () => {
100
110
  await assertExistance( publishPanelSelector, false );
101
111
  await assertExistance( savePanelSelector, false );
102
112
 
103
- // Add a template part and edit it.
104
- await insertBlock( 'Template Part' );
105
- const createNewButton = await page.waitForXPath(
106
- createNewButtonSelector
107
- );
108
- await createNewButton.click();
109
- const confirmTitleButton = await page.waitForSelector(
110
- confirmTitleButtonSelector
111
- );
112
- await confirmTitleButton.click();
113
-
114
- await page.waitForSelector( activatedTemplatePartSelector );
115
- await page.click( '.block-editor-button-block-appender' );
116
- await page.click( '.editor-block-list-item-paragraph' );
117
- await page.keyboard.type( 'some words...' );
113
+ // Add a reusable block and edit it.
114
+ await createReusableBlock( 'Hi!', 'Test' );
115
+ await page.waitForSelector( 'p[data-type="core/paragraph"]' );
116
+ await page.click( 'p[data-type="core/paragraph"]' );
117
+ await page.keyboard.type( 'Oh!' );
118
118
 
119
119
  // Should trigger multi-entity save button once template part edited.
120
120
  await assertMultiSaveEnabled();
@@ -145,7 +145,10 @@ describe( 'Multi-entity save flow', () => {
145
145
  await assertExistance( savePanelSelector, false );
146
146
 
147
147
  // Close publish panel.
148
- await page.click( closePanelButtonSelector );
148
+ const closePanelButton = await page.waitForSelector(
149
+ closePanelButtonSelector
150
+ );
151
+ await closePanelButton.click();
149
152
 
150
153
  // Verify saving is disabled.
151
154
  const draftSaved = await page.waitForSelector( draftSavedSelector );
@@ -154,25 +157,32 @@ describe( 'Multi-entity save flow', () => {
154
157
  await assertExistance( saveA11ySelector, false );
155
158
 
156
159
  await publishPost();
160
+ // Wait for the success notice specifically for the published post.
161
+ // `publishPost()` has a similar check but it only checks for the
162
+ // existence of any snackbars. In this case, there's another "Site updated"
163
+ // notice which will be sufficient for that and thus creating a false-positive.
164
+ await page.waitForXPath(
165
+ '//*[@id="a11y-speak-polite"][contains(text(), "Post published")]'
166
+ );
157
167
 
158
168
  // Update the post.
159
169
  await page.click( '.editor-post-title' );
160
170
  await page.keyboard.type( '...more title!' );
161
171
 
162
172
  // Verify update button is enabled.
163
- const enabledSaveButton = await page.$( enabledSavePostSelector );
173
+ const enabledSaveButton = await page.waitForSelector(
174
+ enabledSavePostSelector
175
+ );
164
176
  expect( enabledSaveButton ).not.toBeNull();
165
177
  // Verify multi-entity saving not enabled.
166
178
  await assertMultiSaveDisabled();
167
179
  await assertExistance( saveA11ySelector, false );
168
180
 
169
- // Update template part.
170
- await page.click( templatePartSelector );
171
- await page.click(
172
- `${ templatePartSelector } .wp-block[data-type="core/paragraph"]`
173
- );
174
- await page.keyboard.type( '...some more words...' );
175
- await page.keyboard.press( 'Enter' );
181
+ // Update reusable block again.
182
+ await page.click( 'p[data-type="core/paragraph"]' );
183
+ // We need to click again due to the clickthrough overlays in reusable blocks.
184
+ await page.click( 'p[data-type="core/paragraph"]' );
185
+ await page.keyboard.type( 'R!' );
176
186
 
177
187
  // Multi-entity saving should be enabled.
178
188
  await assertMultiSaveEnabled();
@@ -185,7 +195,9 @@ describe( 'Multi-entity save flow', () => {
185
195
 
186
196
  await insertBlock( 'Site Title' );
187
197
  // Ensure title is retrieved before typing.
188
- await page.waitForXPath( '//a[contains(text(), "gutenberg")]' );
198
+ await page.waitForXPath(
199
+ `//a[contains(text(), "${ originalSiteTitle }")]`
200
+ );
189
201
  const editableSiteTitleSelector =
190
202
  '.wp-block-site-title a[contenteditable="true"]';
191
203
  await page.waitForSelector( editableSiteTitleSelector );
@@ -211,23 +223,16 @@ describe( 'Multi-entity save flow', () => {
211
223
  await checkboxInputs[ 1 ].click();
212
224
  await page.click( entitiesSaveSelector );
213
225
 
226
+ // Wait for the snackbar notice that the post has been published.
227
+ await page.waitForSelector( '.components-snackbar' );
228
+
214
229
  await clickButton( 'Update…' );
215
230
  await page.waitForSelector( savePanelSelector );
231
+
232
+ await page.waitForSelector( checkboxInputSelector );
216
233
  checkboxInputs = await page.$$( checkboxInputSelector );
217
- expect( checkboxInputs ).toHaveLength( 1 );
218
234
 
219
- // Reset site entity to default value to not affect other tests.
220
- await page.evaluate( () => {
221
- wp.data
222
- .dispatch( 'core' )
223
- .editEntityRecord( 'root', 'site', undefined, {
224
- title: 'gutenberg',
225
- description: 'Just another WordPress site',
226
- } );
227
- wp.data
228
- .dispatch( 'core' )
229
- .saveEditedEntityRecord( 'root', 'site', undefined );
230
- } );
235
+ expect( checkboxInputs ).toHaveLength( 1 );
231
236
  } );
232
237
  } );
233
238
 
@@ -238,6 +243,19 @@ describe( 'Multi-entity save flow', () => {
238
243
  const disabledSaveSiteSelector = `${ saveSiteSelector }[aria-disabled=true]`;
239
244
  const saveA11ySelector = '.edit-site-editor__toggle-save-panel-button';
240
245
 
246
+ const saveAllChanges = async () => {
247
+ // Clicking button should open panel with boxes checked.
248
+ await page.click( activeSaveSiteSelector );
249
+ await page.waitForSelector( savePanelSelector );
250
+ await assertAllBoxesChecked();
251
+
252
+ // Save a11y button should not be present with save panel open.
253
+ await assertExistance( saveA11ySelector, false );
254
+
255
+ // Saving should result in items being saved.
256
+ await page.click( entitiesSaveSelector );
257
+ };
258
+
241
259
  it( 'Save flow should work as expected', async () => {
242
260
  // Navigate to site editor.
243
261
  await siteEditor.visit( {
@@ -249,7 +267,7 @@ describe( 'Multi-entity save flow', () => {
249
267
  // Select the header template part via list view.
250
268
  await page.click( '.edit-site-header-toolbar__list-view-toggle' );
251
269
  const headerTemplatePartListViewButton = await page.waitForXPath(
252
- '//button[contains(@class, "block-editor-list-view-block-select-button")][contains(., "Header")]'
270
+ '//a[contains(@class, "block-editor-list-view-block-select-button")][contains(., "Header")]'
253
271
  );
254
272
  headerTemplatePartListViewButton.click();
255
273
  await page.click( 'button[aria-label="Close list view sidebar"]' );
@@ -267,20 +285,55 @@ describe( 'Multi-entity save flow', () => {
267
285
  // Save a11y button should be present.
268
286
  await assertExistance( saveA11ySelector, true );
269
287
 
270
- // Clicking button should open panel with boxes checked.
271
- await page.click( activeSaveSiteSelector );
272
- await page.waitForSelector( savePanelSelector );
273
- await assertAllBoxesChecked();
288
+ // Save all changes.
289
+ await saveAllChanges();
274
290
 
275
- // Save a11y button should not be present with save panel open.
276
- await assertExistance( saveA11ySelector, false );
277
-
278
- // Saving should result in items being saved.
279
- await page.click( entitiesSaveSelector );
280
291
  const disabledButton = await page.waitForSelector(
281
292
  disabledSaveSiteSelector
282
293
  );
283
294
  expect( disabledButton ).not.toBeNull();
284
295
  } );
296
+
297
+ it( 'Save flow should allow re-saving after changing the same block attribute', async () => {
298
+ // Navigate to site editor.
299
+ await siteEditor.visit( {
300
+ postId: 'tt1-blocks//index',
301
+ postType: 'wp_template',
302
+ } );
303
+ await siteEditor.disableWelcomeGuide();
304
+
305
+ // Insert a paragraph at the bottom.
306
+ await insertBlock( 'Paragraph' );
307
+
308
+ // Open the block settings.
309
+ await page.click( 'button[aria-label="Settings"]' );
310
+
311
+ // Click on font size selector.
312
+ await page.click( 'button[aria-label="Font size"]' );
313
+
314
+ // Click on a different font size.
315
+ const extraSmallFontSize = await page.waitForXPath(
316
+ '//li[contains(text(), "Extra small")]'
317
+ );
318
+ await extraSmallFontSize.click();
319
+
320
+ // Save all changes.
321
+ await saveAllChanges();
322
+
323
+ // Click on font size selector again.
324
+ await page.click( 'button[aria-label="Font size"]' );
325
+
326
+ // Select another font size.
327
+ const normalFontSize = await page.waitForXPath(
328
+ '//li[contains(text(), "Normal")]'
329
+ );
330
+ await normalFontSize.click();
331
+
332
+ // Assert that the save button has been re-enabled.
333
+ const saveButton = await page.waitForSelector(
334
+ activeSaveSiteSelector
335
+ );
336
+ expect( saveButton ).not.toBeNull();
337
+ } );
285
338
  } );
286
339
  } );
@@ -77,12 +77,11 @@ describe( 'Settings sidebar', () => {
77
77
 
78
78
  expect( templateCardBeforeNavigation ).toMatchObject( {
79
79
  title: 'Index',
80
- description:
81
- 'The default template used when no other template is available. This is a required template in WordPress.',
80
+ description: 'Displays posts.',
82
81
  } );
83
82
  expect( templateCardAfterNavigation ).toMatchObject( {
84
83
  title: '404',
85
- description: 'Template shown when no content is found.',
84
+ description: 'Displays when no content is found.',
86
85
  } );
87
86
  } );
88
87
  } );
@@ -2,9 +2,7 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import {
5
- createNewPost,
6
5
  insertBlock,
7
- disablePrePublishChecks,
8
6
  trashAllPosts,
9
7
  activateTheme,
10
8
  getAllBlocks,
@@ -260,72 +258,94 @@ describe( 'Template Part', () => {
260
258
  finalTemplateParts.length - initialTemplateParts.length
261
259
  ).toBe( 1 );
262
260
  } );
263
- } );
264
-
265
- describe( 'Template part placeholder', () => {
266
- // Test constants for template part.
267
- const testContent = 'some words...';
268
-
269
- // Selectors
270
- const entitiesSaveSelector =
271
- '.editor-entities-saved-states__save-button';
272
- const savePostSelector = '.editor-post-publish-button__button';
273
- const templatePartSelector = '*[data-type="core/template-part"]';
274
- const activatedTemplatePartSelector = `${ templatePartSelector }.block-editor-block-list__layout`;
275
- const testContentSelector = `//p[contains(., "${ testContent }")]`;
276
- const createNewButtonSelector =
277
- '//button[contains(text(), "New template part")]';
278
- const chooseExistingButtonSelector =
279
- '//button[contains(text(), "Choose existing")]';
280
- const confirmTitleButtonSelector =
281
- '.wp-block-template-part__placeholder-create-new__title-form .components-button.is-primary';
282
-
283
- it( 'Should insert new template part on creation', async () => {
284
- await createNewPost();
285
- await disablePrePublishChecks();
286
- // Create new template part.
287
- await insertBlock( 'Template Part' );
288
- await page.waitForXPath( chooseExistingButtonSelector );
289
- const [ createNewButton ] = await page.$x(
290
- createNewButtonSelector
291
- );
292
- await createNewButton.click();
293
- const confirmTitleButton = await page.waitForSelector(
294
- confirmTitleButtonSelector
295
- );
296
- await page.keyboard.press( 'Tab' );
297
- await page.keyboard.press( 'Tab' );
298
- await page.keyboard.type( 'Create New' );
299
- await confirmTitleButton.click();
300
-
301
- const newTemplatePart = await page.waitForSelector(
302
- activatedTemplatePartSelector
303
- );
304
- expect( newTemplatePart ).toBeTruthy();
305
-
306
- // Finish creating template part, insert some text, and save.
307
- await page.click( '.block-editor-button-block-appender' );
308
- await page.click( '.editor-block-list-item-paragraph' );
309
- await page.keyboard.type( testContent );
310
- await page.click( savePostSelector );
311
- await page.click( entitiesSaveSelector );
312
-
313
- await createNewPost();
314
- // Try to insert the template part we created.
315
- await insertBlock( 'Template Part' );
316
- const chooseExistingButton = await page.waitForXPath(
317
- chooseExistingButtonSelector
318
- );
319
- await chooseExistingButton.click();
320
- const preview = await page.waitForSelector(
321
- '[aria-label="Create New"]'
322
- );
323
- await preview.click();
324
- await page.waitForSelector( activatedTemplatePartSelector );
325
- const templatePartContent = await page.waitForXPath(
326
- testContentSelector
327
- );
328
- expect( templatePartContent ).toBeTruthy();
261
+ describe( 'Template part placeholder', () => {
262
+ // Test constants for template part.
263
+ const testContent = 'some words...';
264
+
265
+ // Selectors
266
+ const entitiesSaveSelector =
267
+ '.editor-entities-saved-states__save-button';
268
+ const savePostSelector = '.edit-site-save-button__button';
269
+ const templatePartSelector = '*[data-type="core/template-part"]';
270
+ const activatedTemplatePartSelector = `${ templatePartSelector }.block-editor-block-list__layout`;
271
+ const createNewButtonSelector =
272
+ '//button[contains(text(), "New template part")]';
273
+ const chooseExistingButtonSelector =
274
+ '//button[contains(text(), "Choose existing")]';
275
+ const confirmTitleButtonSelector =
276
+ '.wp-block-template-part__placeholder-create-new__title-form .components-button.is-primary';
277
+
278
+ it( 'Should insert new template part on creation', async () => {
279
+ let siteEditorCanvas = canvas();
280
+ await awaitHeaderAndFooterLoad();
281
+
282
+ // Create new template part.
283
+ await insertBlock( 'Template Part' );
284
+ await siteEditorCanvas.waitForXPath(
285
+ chooseExistingButtonSelector
286
+ );
287
+ const [ createNewButton ] = await siteEditorCanvas.$x(
288
+ createNewButtonSelector
289
+ );
290
+ await createNewButton.click();
291
+ const confirmTitleButton = await page.waitForSelector(
292
+ confirmTitleButtonSelector
293
+ );
294
+ await page.keyboard.press( 'Tab' );
295
+ await page.keyboard.press( 'Tab' );
296
+ await page.keyboard.type( 'Create New' );
297
+ await confirmTitleButton.click();
298
+
299
+ const newTemplatePart = await siteEditorCanvas.waitForSelector(
300
+ activatedTemplatePartSelector
301
+ );
302
+ expect( newTemplatePart ).toBeTruthy();
303
+
304
+ // Finish creating template part, insert some text, and save.
305
+ await siteEditorCanvas.waitForSelector(
306
+ '.block-editor-button-block-appender'
307
+ );
308
+ await siteEditorCanvas.click(
309
+ '.block-editor-button-block-appender'
310
+ );
311
+ await page.waitForSelector(
312
+ '.editor-block-list-item-paragraph'
313
+ );
314
+ await page.click( '.editor-block-list-item-paragraph' );
315
+ await page.keyboard.type( testContent );
316
+ await page.click( savePostSelector );
317
+ await page.click( entitiesSaveSelector );
318
+
319
+ // Reload the page so as the new template part is available in the existing template parts.
320
+ await siteEditor.visit();
321
+ siteEditorCanvas = canvas();
322
+ await awaitHeaderAndFooterLoad();
323
+ // Try to insert the template part we created.
324
+ await insertBlock( 'Template Part' );
325
+ const chooseExistingButton = await siteEditorCanvas.waitForXPath(
326
+ chooseExistingButtonSelector
327
+ );
328
+ await chooseExistingButton.click();
329
+ await page.waitForSelector(
330
+ '.wp-block-template-part__selection-preview-container'
331
+ );
332
+ const preview = await page.waitForSelector(
333
+ '.wp-block-template-part__selection-preview-item[aria-label="Create New"]'
334
+ );
335
+ await preview.click();
336
+ // We now have the same template part two times in the page, so check accordingly.
337
+ const paragraphs = await siteEditorCanvas.$$eval(
338
+ '[data-type="core/template-part"] > p:first-child',
339
+ ( options ) =>
340
+ options.map( ( option ) => option.textContent )
341
+ );
342
+ expect( paragraphs ).toHaveLength( 2 );
343
+ expect(
344
+ paragraphs.every(
345
+ ( paragraph ) => paragraph === testContent
346
+ )
347
+ ).toBeTruthy();
348
+ } );
329
349
  } );
330
350
  } );
331
351
  } );
@@ -10,6 +10,7 @@ import {
10
10
  clickBlockToolbarButton,
11
11
  deleteAllWidgets,
12
12
  createURL,
13
+ openTypographyToolsPanelMenu,
13
14
  } from '@wordpress/e2e-test-utils';
14
15
 
15
16
  /**
@@ -831,6 +832,9 @@ describe( 'Widgets Customizer', () => {
831
832
  await showMoreSettingsButton.click();
832
833
 
833
834
  // Change `drop cap` (Any change made in this section is sufficient; not required to be `drop cap`).
835
+ await openTypographyToolsPanelMenu();
836
+ await page.click( 'button[aria-label="Show Drop cap"]' );
837
+
834
838
  const [ dropCapToggle ] = await page.$x(
835
839
  "//label[contains(text(), 'Drop cap')]"
836
840
  );