@wordpress/e2e-tests 3.0.7 → 3.0.10-next.a55ed9455a.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 (74) hide show
  1. package/config/setup-performance-test.js +1 -1
  2. package/config/setup-test-framework.js +1 -1
  3. package/package.json +7 -7
  4. package/specs/editor/blocks/__snapshots__/heading.test.js.snap +8 -8
  5. package/specs/editor/blocks/__snapshots__/navigation.test.js.snap +16 -16
  6. package/specs/editor/blocks/__snapshots__/quote.test.js.snap +10 -10
  7. package/specs/editor/blocks/classic.test.js +2 -2
  8. package/specs/editor/blocks/cover.test.js +17 -17
  9. package/specs/editor/blocks/image.test.js +4 -3
  10. package/specs/editor/blocks/list.test.js +1 -1
  11. package/specs/editor/blocks/navigation.test.js +392 -65
  12. package/specs/editor/blocks/table.test.js +1 -1
  13. package/specs/editor/plugins/align-hook.test.js +10 -10
  14. package/specs/editor/plugins/block-context.test.js +1 -1
  15. package/specs/editor/plugins/block-directory-add.test.js +14 -14
  16. package/specs/editor/plugins/custom-post-types.test.js +1 -1
  17. package/specs/editor/plugins/custom-taxonomies.test.js +3 -3
  18. package/specs/editor/plugins/meta-attribute-block.test.js +1 -1
  19. package/specs/editor/plugins/meta-boxes.test.js +3 -3
  20. package/specs/editor/plugins/templates.test.js +1 -1
  21. package/specs/editor/plugins/wp-editor-meta-box.test.js +1 -1
  22. package/specs/editor/various/__snapshots__/block-grouping.test.js.snap +4 -4
  23. package/specs/editor/various/__snapshots__/inserting-blocks.test.js.snap +2 -2
  24. package/specs/editor/various/__snapshots__/keep-styles-on-block-transforms.test.js.snap +3 -3
  25. package/specs/editor/various/autosave.test.js +19 -19
  26. package/specs/editor/various/block-deletion.test.js +5 -5
  27. package/specs/editor/various/block-grouping.test.js +29 -12
  28. package/specs/editor/various/block-hierarchy-navigation.test.js +5 -5
  29. package/specs/editor/various/change-detection.test.js +3 -3
  30. package/specs/editor/various/compatibility-classic-editor.test.js +1 -1
  31. package/specs/editor/various/copy-cut-paste-whole-blocks.test.js +7 -7
  32. package/specs/editor/various/datepicker.test.js +1 -1
  33. package/specs/editor/various/duplicating-blocks.test.js +3 -3
  34. package/specs/editor/various/editor-modes.test.js +5 -5
  35. package/specs/editor/various/inserting-blocks.test.js +6 -6
  36. package/specs/editor/various/invalid-block.test.js +4 -4
  37. package/specs/editor/various/is-typing.test.js +8 -8
  38. package/specs/editor/various/keyboard-navigable-blocks.test.js +2 -2
  39. package/specs/editor/various/links.test.js +90 -90
  40. package/specs/editor/various/list-view.test.js +142 -1
  41. package/specs/editor/various/manage-reusable-blocks.test.js +5 -5
  42. package/specs/editor/various/multi-block-selection.test.js +86 -2
  43. package/specs/editor/various/navigable-toolbar.test.js +1 -1
  44. package/specs/editor/various/new-post-default-content.test.js +2 -2
  45. package/specs/editor/various/new-post.test.js +1 -1
  46. package/specs/editor/various/nux.test.js +11 -11
  47. package/specs/editor/various/popovers.test.js +3 -3
  48. package/specs/editor/various/post-editor-template-mode.test.js +189 -11
  49. package/specs/editor/various/post-visibility.test.js +1 -1
  50. package/specs/editor/various/preferences.test.js +1 -1
  51. package/specs/editor/various/preview.test.js +8 -4
  52. package/specs/editor/various/publish-button.test.js +2 -2
  53. package/specs/editor/various/publishing.test.js +50 -1
  54. package/specs/editor/various/reusable-blocks.test.js +31 -31
  55. package/specs/editor/various/rich-text.test.js +1 -1
  56. package/specs/editor/various/splitting-merging.test.js +6 -6
  57. package/specs/editor/various/style-variation.test.js +2 -2
  58. package/specs/editor/various/switch-to-draft.test.js +256 -0
  59. package/specs/editor/various/taxonomies.test.js +1 -1
  60. package/specs/editor/various/toolbar-roving-tabindex.test.js +1 -1
  61. package/specs/editor/various/writing-flow.test.js +85 -20
  62. package/specs/experiments/navigation-editor.test.js +168 -3
  63. package/specs/performance/post-editor.test.js +7 -7
  64. package/specs/performance/site-editor.test.js +6 -7
  65. package/specs/site-editor/document-settings.test.js +8 -8
  66. package/specs/site-editor/multi-entity-editing.test.js +6 -6
  67. package/specs/site-editor/multi-entity-saving.test.js +5 -4
  68. package/specs/site-editor/settings-sidebar.test.js +5 -5
  69. package/specs/site-editor/site-editor-export.test.js +3 -3
  70. package/specs/site-editor/site-editor-inserter.test.js +3 -3
  71. package/specs/site-editor/template-part.test.js +27 -26
  72. package/specs/site-editor/template-revert.test.js +12 -22
  73. package/specs/widgets/customizing-widgets.test.js +14 -9
  74. package/specs/widgets/editing-widgets.test.js +8 -7
@@ -77,7 +77,7 @@ describe( 'Block context', () => {
77
77
  );
78
78
  expect( content ).toMatch( /^123,\d+,post$/ );
79
79
 
80
- // Clean up
80
+ // Clean up.
81
81
  await editorPage.bringToFront();
82
82
  await previewPage.close();
83
83
  } );
@@ -12,7 +12,7 @@ import {
12
12
 
13
13
  const BLOCK1_NAME = 'block-directory-test-block/main-block';
14
14
 
15
- // Urls to mock
15
+ // Urls to mock.
16
16
  const SEARCH_URLS = [
17
17
  '/wp/v2/block-directory/search',
18
18
  `rest_route=${ encodeURIComponent( '/wp/v2/block-directory/search' ) }`,
@@ -30,7 +30,7 @@ const INSTALL_URLS = [
30
30
  `rest_route=${ encodeURIComponent( '/wp/v2/plugins' ) }`,
31
31
  ];
32
32
 
33
- // Example Blocks
33
+ // Example Blocks.
34
34
  const MOCK_BLOCK1 = {
35
35
  name: BLOCK1_NAME,
36
36
  title: 'Block Directory Test Block',
@@ -44,7 +44,7 @@ const MOCK_BLOCK1 = {
44
44
  author: 'No Author',
45
45
  icon: 'block-default',
46
46
  assets: [
47
- 'https://fake_url.com/block.js', // we will mock this
47
+ 'https://fake_url.com/block.js', // We will mock this.
48
48
  ],
49
49
  humanized_updated: '5 months ago',
50
50
  links: {},
@@ -82,7 +82,7 @@ const MOCK_BLOCK2 = {
82
82
  id: 'block-directory-test-secondary-block',
83
83
  };
84
84
 
85
- // Block that will be registered
85
+ // Block that will be registered.
86
86
  const block = `( function() {
87
87
  var registerBlockType = wp.blocks.registerBlockType;
88
88
  var el = wp.element.createElement;
@@ -112,26 +112,26 @@ const MOCK_EMPTY_RESPONSES = [
112
112
 
113
113
  const MOCK_BLOCKS_RESPONSES = [
114
114
  {
115
- // Mock response for search with the block
115
+ // Mock response for search with the block.
116
116
  match: ( request ) =>
117
117
  matchUrl( request.url(), SEARCH_URLS ) &&
118
118
  request.method() === 'GET',
119
119
  onRequestMatch: createJSONResponse( [ MOCK_BLOCK1, MOCK_BLOCK2 ] ),
120
120
  },
121
121
  {
122
- // Mock response for block type
122
+ // Mock response for block type.
123
123
  match: ( request ) => matchUrl( request.url(), BLOCK_TYPE_URLS ),
124
124
  onRequestMatch: createJSONResponse( {} ),
125
125
  },
126
126
  {
127
- // Mock response for install
127
+ // Mock response for install.
128
128
  match: ( request ) => matchUrl( request.url(), INSTALL_URLS ),
129
129
  onRequestMatch: createJSONResponse(
130
130
  MOCK_INSTALLED_BLOCK_PLUGIN_DETAILS
131
131
  ),
132
132
  },
133
133
  {
134
- // Mock the response for the js asset once it gets injected
134
+ // Mock the response for the js asset once it gets injected.
135
135
  match: ( request ) => request.url().includes( MOCK_BLOCK1.assets[ 0 ] ),
136
136
  onRequestMatch: createResponse(
137
137
  Buffer.from( block, 'utf8' ),
@@ -171,13 +171,13 @@ describe( 'adding blocks from block directory', () => {
171
171
  } );
172
172
 
173
173
  it( 'Should show an empty state when no plugin is found.', async () => {
174
- // Be super weird so there won't be a matching block installed
174
+ // Be super weird so there won't be a matching block installed.
175
175
  const impossibleBlockName = '@#$@@Dsdsdfw2#$@';
176
176
 
177
- // Return an empty list of plugins
177
+ // Return an empty list of plugins.
178
178
  await setUpResponseMocking( MOCK_EMPTY_RESPONSES );
179
179
 
180
- // Search for the block via the inserter
180
+ // Search for the block via the inserter.
181
181
  await searchForBlock( impossibleBlockName );
182
182
 
183
183
  const selectorContent = await page.evaluate(
@@ -191,15 +191,15 @@ describe( 'adding blocks from block directory', () => {
191
191
  } );
192
192
 
193
193
  it( 'Should be able to add (the first) block.', async () => {
194
- // Setup our mocks
194
+ // Setup our mocks.
195
195
  await setUpResponseMocking( MOCK_BLOCKS_RESPONSES );
196
196
 
197
- // Search for the block via the inserter
197
+ // Search for the block via the inserter.
198
198
  await insertBlockDirectoryBlock( MOCK_BLOCK1.title );
199
199
 
200
200
  await page.waitForSelector( `div[data-type="${ MOCK_BLOCK1.name }"]` );
201
201
 
202
- // The block will auto select and get added, make sure we see it in the content
202
+ // The block will auto select and get added, make sure we see it in the content.
203
203
  expect( await getEditedPostContent() ).toMatchSnapshot();
204
204
  } );
205
205
  } );
@@ -13,7 +13,7 @@ import {
13
13
  const openPageAttributesPanel = async () => {
14
14
  const openButton = await findSidebarPanelWithTitle( 'Page Attributes' );
15
15
 
16
- // Get the classes from the panel
16
+ // Get the classes from the panel.
17
17
  const buttonClassName = await (
18
18
  await openButton.getProperty( 'className' )
19
19
  ).jsonValue();
@@ -29,7 +29,7 @@ describe( 'Custom Taxonomies labels are used', () => {
29
29
  const openButton = await findSidebarPanelWithTitle( 'Model' );
30
30
  expect( openButton ).not.toBeFalsy();
31
31
 
32
- // Get the classes from the panel
32
+ // Get the classes from the panel.
33
33
  const buttonClassName = await (
34
34
  await openButton.getProperty( 'className' )
35
35
  ).jsonValue();
@@ -39,13 +39,13 @@ describe( 'Custom Taxonomies labels are used', () => {
39
39
  await openButton.click();
40
40
  }
41
41
 
42
- // Check the add new button
42
+ // Check the add new button.
43
43
  const labelNew = await page.$x(
44
44
  "//label[@class='components-form-token-field__label' and contains(text(), 'Add New Model')]"
45
45
  );
46
46
  expect( labelNew ).not.toBeFalsy();
47
47
 
48
- // Fill with one entry
48
+ // Fill with one entry.
49
49
  await page.type(
50
50
  'input.components-form-token-field__input',
51
51
  'Model 1'
@@ -62,7 +62,7 @@ describe( 'Block with a meta attribute', () => {
62
62
  // Clicking the input selects the block,
63
63
  // and selecting the block enables the sync data mode
64
64
  // as otherwise the asynchronous re-rendering of unselected blocks
65
- // may cause the input to have not yet been updated for the other blocks
65
+ // may cause the input to have not yet been updated for the other blocks.
66
66
  await input.click();
67
67
  const inputValue = await input.getProperty( 'value' );
68
68
  expect( await inputValue.jsonValue() ).toBe(
@@ -86,7 +86,7 @@ describe( 'Meta boxes', () => {
86
86
  await viewPostLinks[ 0 ].click();
87
87
  await page.waitForNavigation();
88
88
 
89
- // Retrieve the excerpt used as meta
89
+ // Retrieve the excerpt used as meta.
90
90
  const metaExcerpt = await page.evaluate( () => {
91
91
  return document
92
92
  .querySelector( 'meta[property="gutenberg:hello"]' )
@@ -101,7 +101,7 @@ describe( 'Meta boxes', () => {
101
101
  await page.keyboard.type( 'Excerpt from content.' );
102
102
  await page.type( '.editor-post-title__input', 'A published post' );
103
103
 
104
- // Open the excerpt panel
104
+ // Open the excerpt panel.
105
105
  await openDocumentSettingsSidebar();
106
106
  const excerptButton = await findSidebarPanelToggleButtonWithTitle(
107
107
  'Excerpt'
@@ -126,7 +126,7 @@ describe( 'Meta boxes', () => {
126
126
  await viewPostLinks[ 0 ].click();
127
127
  await page.waitForNavigation();
128
128
 
129
- // Retrieve the excerpt used as meta
129
+ // Retrieve the excerpt used as meta.
130
130
  const metaExcerpt = await page.evaluate( () => {
131
131
  return document
132
132
  .querySelector( 'meta[property="gutenberg:hello"]' )
@@ -105,7 +105,7 @@ describe( 'templates', () => {
105
105
  await page.reload();
106
106
  await page.waitForSelector( '.edit-post-layout' );
107
107
 
108
- // Wait a bit more for getEditedPostContent to be correct
108
+ // Wait a bit more for getEditedPostContent to be correct.
109
109
  await page.waitForSelector(
110
110
  '.block-editor-default-block-appender__content'
111
111
  );
@@ -22,7 +22,7 @@ describe( 'WP Editor Meta Boxes', () => {
22
22
  // Add title to enable valid non-empty post save.
23
23
  await page.type( '.editor-post-title__input', 'Hello Meta' );
24
24
 
25
- // Type something
25
+ // Type something.
26
26
  await expect( page ).toClick( '#test_tinymce_id-html' );
27
27
  await page.type( '#test_tinymce_id', 'Typing in a metabox' );
28
28
  await page.click( '#test_tinymce_id-tmce' );
@@ -3,7 +3,7 @@
3
3
  exports[`Block Grouping Group creation creates a group from multiple blocks of different types via block transforms 1`] = `
4
4
  "<!-- wp:group -->
5
5
  <div class=\\"wp-block-group\\"><!-- wp:heading -->
6
- <h2 id=\\"group-heading\\">Group Heading</h2>
6
+ <h2>Group Heading</h2>
7
7
  <!-- /wp:heading -->
8
8
 
9
9
  <!-- wp:image -->
@@ -51,7 +51,7 @@ exports[`Block Grouping Group creation creates a group from multiple blocks of t
51
51
  exports[`Block Grouping Group creation groups and ungroups multiple blocks of different types via options toolbar 1`] = `
52
52
  "<!-- wp:group -->
53
53
  <div class=\\"wp-block-group\\"><!-- wp:heading -->
54
- <h2 id=\\"group-heading\\">Group Heading</h2>
54
+ <h2>Group Heading</h2>
55
55
  <!-- /wp:heading -->
56
56
 
57
57
  <!-- wp:image -->
@@ -66,7 +66,7 @@ exports[`Block Grouping Group creation groups and ungroups multiple blocks of di
66
66
 
67
67
  exports[`Block Grouping Group creation groups and ungroups multiple blocks of different types via options toolbar 2`] = `
68
68
  "<!-- wp:heading -->
69
- <h2 id=\\"group-heading\\">Group Heading</h2>
69
+ <h2>Group Heading</h2>
70
70
  <!-- /wp:heading -->
71
71
 
72
72
  <!-- wp:image -->
@@ -81,7 +81,7 @@ exports[`Block Grouping Group creation groups and ungroups multiple blocks of di
81
81
  exports[`Block Grouping Preserving selected blocks attributes preserves width alignment settings of selected blocks 1`] = `
82
82
  "<!-- wp:group {\\"align\\":\\"full\\"} -->
83
83
  <div class=\\"wp-block-group alignfull\\"><!-- wp:heading -->
84
- <h2 id=\\"group-heading\\">Group Heading</h2>
84
+ <h2>Group Heading</h2>
85
85
  <!-- /wp:heading -->
86
86
 
87
87
  <!-- wp:image {\\"align\\":\\"full\\"} -->
@@ -71,7 +71,7 @@ exports[`Inserting blocks inserts a block in proper place after having clicked \
71
71
  <!-- /wp:paragraph -->
72
72
 
73
73
  <!-- wp:heading -->
74
- <h2 id=\\"heading\\">Heading</h2>
74
+ <h2>Heading</h2>
75
75
  <!-- /wp:heading -->
76
76
 
77
77
  <!-- wp:paragraph -->
@@ -93,7 +93,7 @@ exports[`Inserting blocks inserts a block in proper place after having clicked \
93
93
  <!-- /wp:cover -->
94
94
 
95
95
  <!-- wp:heading -->
96
- <h2 id=\\"heading\\">Heading</h2>
96
+ <h2>Heading</h2>
97
97
  <!-- /wp:heading -->
98
98
 
99
99
  <!-- wp:paragraph -->
@@ -14,15 +14,15 @@ exports[`Keep styles on block transforms Should keep the font size during a tran
14
14
 
15
15
  exports[`Keep styles on block transforms Should keep the font size during a transform from multiple blocks into multiple blocks 1`] = `
16
16
  "<!-- wp:heading {\\"fontSize\\":\\"large\\"} -->
17
- <h2 class=\\"has-large-font-size\\" id=\\"line-1-to-be-made-large\\">Line 1 to be made large</h2>
17
+ <h2 class=\\"has-large-font-size\\">Line 1 to be made large</h2>
18
18
  <!-- /wp:heading -->
19
19
 
20
20
  <!-- wp:heading {\\"fontSize\\":\\"large\\"} -->
21
- <h2 class=\\"has-large-font-size\\" id=\\"line-2-to-be-made-large\\">Line 2 to be made large</h2>
21
+ <h2 class=\\"has-large-font-size\\">Line 2 to be made large</h2>
22
22
  <!-- /wp:heading -->
23
23
 
24
24
  <!-- wp:heading {\\"fontSize\\":\\"large\\"} -->
25
- <h2 class=\\"has-large-font-size\\" id=\\"line-3-to-be-made-large\\">Line 3 to be made large</h2>
25
+ <h2 class=\\"has-large-font-size\\">Line 3 to be made large</h2>
26
26
  <!-- /wp:heading -->"
27
27
  `;
28
28
 
@@ -77,7 +77,7 @@ describe( 'autosave', () => {
77
77
 
78
78
  it( 'should save to sessionStorage', async () => {
79
79
  // Wait for the original timeout to kick in, it will schedule
80
- // another run using the updated interval length of AUTOSAVE_INTERVAL_SECONDS
80
+ // another run using the updated interval length of AUTOSAVE_INTERVAL_SECONDS.
81
81
  await sleep( 15 );
82
82
 
83
83
  await clickBlockAppender();
@@ -86,7 +86,7 @@ describe( 'autosave', () => {
86
86
  await sleep( 1 );
87
87
  await page.keyboard.type( ' after save' );
88
88
 
89
- // Wait long enough for local autosave to kick in
89
+ // Wait long enough for local autosave to kick in.
90
90
  await sleep( AUTOSAVE_INTERVAL_SECONDS + 1 );
91
91
 
92
92
  const id = await getCurrentPostId();
@@ -101,11 +101,11 @@ describe( 'autosave', () => {
101
101
  await saveDraftWithKeyboard();
102
102
  await page.keyboard.type( ' after save' );
103
103
 
104
- // Trigger local autosave
104
+ // Trigger local autosave.
105
105
  await page.evaluate( () =>
106
106
  window.wp.data.dispatch( 'core/editor' ).autosave( { local: true } )
107
107
  );
108
- // Reload without saving on the server
108
+ // Reload without saving on the server.
109
109
  await page.reload();
110
110
  await page.waitForSelector( '.edit-post-layout' );
111
111
 
@@ -129,7 +129,7 @@ describe( 'autosave', () => {
129
129
  await page.keyboard.type( 'before save' );
130
130
  await saveDraft();
131
131
 
132
- // Fake local autosave
132
+ // Fake local autosave.
133
133
  await page.evaluate(
134
134
  ( postId ) =>
135
135
  window.sessionStorage.setItem(
@@ -161,13 +161,13 @@ describe( 'autosave', () => {
161
161
  } );
162
162
 
163
163
  it( 'should clear local autosave after successful remote autosave', async () => {
164
- // Edit, save draft, edit again
164
+ // Edit, save draft, edit again.
165
165
  await clickBlockAppender();
166
166
  await page.keyboard.type( 'before save' );
167
167
  await saveDraftWithKeyboard();
168
168
  await page.keyboard.type( ' after save' );
169
169
 
170
- // Trigger local autosave
170
+ // Trigger local autosave.
171
171
  await page.evaluate( () =>
172
172
  window.wp.data.dispatch( 'core/editor' ).autosave( { local: true } )
173
173
  );
@@ -175,7 +175,7 @@ describe( 'autosave', () => {
175
175
  await page.evaluate( () => window.sessionStorage.length )
176
176
  ).toBeGreaterThanOrEqual( 1 );
177
177
 
178
- // Trigger remote autosave
178
+ // Trigger remote autosave.
179
179
  await page.evaluate( () =>
180
180
  window.wp.data.dispatch( 'core/editor' ).autosave()
181
181
  );
@@ -185,13 +185,13 @@ describe( 'autosave', () => {
185
185
  } );
186
186
 
187
187
  it( "shouldn't clear local autosave if remote autosave fails", async () => {
188
- // Edit, save draft, edit again
188
+ // Edit, save draft, edit again.
189
189
  await clickBlockAppender();
190
190
  await page.keyboard.type( 'before save' );
191
191
  await saveDraftWithKeyboard();
192
192
  await page.keyboard.type( ' after save' );
193
193
 
194
- // Trigger local autosave
194
+ // Trigger local autosave.
195
195
  await page.evaluate( () =>
196
196
  window.wp.data.dispatch( 'core/editor' ).autosave( { local: true } )
197
197
  );
@@ -199,7 +199,7 @@ describe( 'autosave', () => {
199
199
  await page.evaluate( () => window.sessionStorage.length )
200
200
  ).toBe( 1 );
201
201
 
202
- // Bring network down and attempt to autosave remotely
202
+ // Bring network down and attempt to autosave remotely.
203
203
  toggleOfflineMode( true );
204
204
  await page.evaluate( () =>
205
205
  window.wp.data.dispatch( 'core/editor' ).autosave()
@@ -210,13 +210,13 @@ describe( 'autosave', () => {
210
210
  } );
211
211
 
212
212
  it( 'should clear local autosave after successful save', async () => {
213
- // Edit, save draft, edit again
213
+ // Edit, save draft, edit again.
214
214
  await clickBlockAppender();
215
215
  await page.keyboard.type( 'before save' );
216
216
  await saveDraftWithKeyboard();
217
217
  await page.keyboard.type( ' after save' );
218
218
 
219
- // Trigger local autosave
219
+ // Trigger local autosave.
220
220
  await page.evaluate( () =>
221
221
  window.wp.data.dispatch( 'core/editor' ).autosave( { local: true } )
222
222
  );
@@ -231,13 +231,13 @@ describe( 'autosave', () => {
231
231
  } );
232
232
 
233
233
  it( "shouldn't clear local autosave if save fails", async () => {
234
- // Edit, save draft, edit again
234
+ // Edit, save draft, edit again.
235
235
  await clickBlockAppender();
236
236
  await page.keyboard.type( 'before save' );
237
237
  await saveDraftWithKeyboard();
238
238
  await page.keyboard.type( ' after save' );
239
239
 
240
- // Trigger local autosave
240
+ // Trigger local autosave.
241
241
  await page.evaluate( () =>
242
242
  window.wp.data.dispatch( 'core/editor' ).autosave( { local: true } )
243
243
  );
@@ -245,7 +245,7 @@ describe( 'autosave', () => {
245
245
  await page.evaluate( () => window.sessionStorage.length )
246
246
  ).toBeGreaterThanOrEqual( 1 );
247
247
 
248
- // Bring network down and attempt to save
248
+ // Bring network down and attempt to save.
249
249
  toggleOfflineMode( true );
250
250
  saveDraftWithKeyboard();
251
251
  expect(
@@ -261,12 +261,12 @@ describe( 'autosave', () => {
261
261
  await page.click( '[data-type="core/paragraph"]' );
262
262
  await page.keyboard.type( ' after publish' );
263
263
 
264
- // Trigger remote autosave
264
+ // Trigger remote autosave.
265
265
  await page.evaluate( () =>
266
266
  window.wp.data.dispatch( 'core/editor' ).autosave()
267
267
  );
268
268
 
269
- // Force conflicting local autosave
269
+ // Force conflicting local autosave.
270
270
  await page.evaluate( () =>
271
271
  window.wp.data.dispatch( 'core/editor' ).autosave( { local: true } )
272
272
  );
@@ -307,7 +307,7 @@ describe( 'autosave', () => {
307
307
  await page.keyboard.type( 'before save' );
308
308
  await saveDraft();
309
309
 
310
- // Fake local autosave
310
+ // Fake local autosave.
311
311
  await page.evaluate(
312
312
  ( postId ) =>
313
313
  window.sessionStorage.setItem(
@@ -15,7 +15,7 @@ import {
15
15
  const addThreeParagraphsToNewPost = async () => {
16
16
  await createNewPost();
17
17
 
18
- // Add demo content
18
+ // Add demo content.
19
19
  await clickBlockAppender();
20
20
  await page.keyboard.type( 'First paragraph' );
21
21
  await page.keyboard.press( 'Enter' );
@@ -40,7 +40,7 @@ const clickOnBlockSettingsMenuRemoveBlockButton = async () => {
40
40
  ( btns ) => btns.length
41
41
  );
42
42
 
43
- // Limit by the number of buttons available
43
+ // Limit by the number of buttons available.
44
44
  while ( --numButtons ) {
45
45
  await page.keyboard.press( 'Tab' );
46
46
 
@@ -50,14 +50,14 @@ const clickOnBlockSettingsMenuRemoveBlockButton = async () => {
50
50
  );
51
51
  } );
52
52
 
53
- // Stop looping once we find the button
53
+ // Stop looping once we find the button.
54
54
  if ( isRemoveButton ) {
55
55
  await pressKeyTimes( 'Enter', 1 );
56
56
  break;
57
57
  }
58
58
  }
59
59
 
60
- // Makes failures more explicit
60
+ // Makes failures more explicit.
61
61
  await expect( isRemoveButton ).toBe( true );
62
62
  };
63
63
 
@@ -66,7 +66,7 @@ describe( 'block deletion -', () => {
66
66
 
67
67
  describe( 'deleting the third block using the Remove Block menu item', () => {
68
68
  it( 'results in two remaining blocks and positions the caret at the end of the second block', async () => {
69
- // The blocks can't be empty to trigger the toolbar
69
+ // The blocks can't be empty to trigger the toolbar.
70
70
  await page.keyboard.type( 'Paragraph to remove' );
71
71
  await clickOnBlockSettingsMenuRemoveBlockButton();
72
72
 
@@ -39,13 +39,13 @@ async function insertBlocksOfMultipleTypes() {
39
39
 
40
40
  describe( 'Block Grouping', () => {
41
41
  beforeEach( async () => {
42
- // Posts are auto-removed at the end of each test run
42
+ // Posts are auto-removed at the end of each test run.
43
43
  await createNewPost();
44
44
  } );
45
45
 
46
46
  describe( 'Group creation', () => {
47
47
  it( 'creates a group from multiple blocks of the same type via block transforms', async () => {
48
- // Creating test blocks
48
+ // Creating test blocks.
49
49
  await insertBlocksOfSameType();
50
50
 
51
51
  // Multiselect via keyboard.
@@ -58,7 +58,7 @@ describe( 'Block Grouping', () => {
58
58
  } );
59
59
 
60
60
  it( 'creates a group from multiple blocks of different types via block transforms', async () => {
61
- // Creating test blocks
61
+ // Creating test blocks.
62
62
  await insertBlocksOfMultipleTypes();
63
63
 
64
64
  // Multiselect via keyboard.
@@ -71,7 +71,7 @@ describe( 'Block Grouping', () => {
71
71
  } );
72
72
 
73
73
  it( 'creates a group from multiple blocks of the same type via options toolbar', async () => {
74
- // Creating test blocks
74
+ // Creating test blocks.
75
75
  await insertBlocksOfSameType();
76
76
 
77
77
  // Multiselect via keyboard.
@@ -85,18 +85,18 @@ describe( 'Block Grouping', () => {
85
85
  } );
86
86
 
87
87
  it( 'groups and ungroups multiple blocks of different types via options toolbar', async () => {
88
- // Creating test blocks
88
+ // Creating test blocks.
89
89
  await insertBlocksOfMultipleTypes();
90
90
  await pressKeyWithModifier( 'primary', 'a' );
91
91
  await pressKeyWithModifier( 'primary', 'a' );
92
92
 
93
- // Group
93
+ // Group.
94
94
  await clickBlockToolbarButton( 'Options' );
95
95
  await clickMenuItem( 'Group' );
96
96
 
97
97
  expect( await getEditedPostContent() ).toMatchSnapshot();
98
98
 
99
- // UnGroup
99
+ // UnGroup.
100
100
  await clickBlockToolbarButton( 'Options' );
101
101
  await clickMenuItem( 'Ungroup' );
102
102
 
@@ -140,24 +140,41 @@ describe( 'Block Grouping', () => {
140
140
  // Make sure the paragraph in reusable block exists.
141
141
  expect( await getParagraphText() ).toEqual( paragraphText );
142
142
  } );
143
+ it( 'should group another Group block via options toolbar', async () => {
144
+ await insertBlock( 'Paragraph' );
145
+ await page.keyboard.type( '1' );
146
+ await clickBlockToolbarButton( 'Options' );
147
+ await clickMenuItem( 'Group' );
148
+ await clickBlockToolbarButton( 'Options' );
149
+ await clickMenuItem( 'Group' );
150
+ expect( await getEditedPostContent() ).toMatchInlineSnapshot( `
151
+ "<!-- wp:group -->
152
+ <div class=\\"wp-block-group\\"><!-- wp:group -->
153
+ <div class=\\"wp-block-group\\"><!-- wp:paragraph -->
154
+ <p>1</p>
155
+ <!-- /wp:paragraph --></div>
156
+ <!-- /wp:group --></div>
157
+ <!-- /wp:group -->"
158
+ ` );
159
+ } );
143
160
  } );
144
161
 
145
162
  describe( 'Grouping Block availability', () => {
146
163
  beforeEach( async () => {
147
- // Disable the Group block
164
+ // Disable the Group block.
148
165
  await page.evaluate( () => {
149
166
  const { dispatch } = wp.data;
150
167
  dispatch( 'core/edit-post' ).hideBlockTypes( [ 'core/group' ] );
151
168
  } );
152
169
 
153
- // Create a Group
170
+ // Create a Group.
154
171
  await insertBlocksOfMultipleTypes();
155
172
  await pressKeyWithModifier( 'primary', 'a' );
156
173
  await pressKeyWithModifier( 'primary', 'a' );
157
174
  } );
158
175
 
159
176
  afterAll( async () => {
160
- // Re-enable the Group block
177
+ // Re-enable the Group block.
161
178
  await page.evaluate( () => {
162
179
  const { dispatch } = wp.data;
163
180
  dispatch( 'core/edit-post' ).showBlockTypes( [ 'core/group' ] );
@@ -239,14 +256,14 @@ describe( 'Block Grouping', () => {
239
256
  } );
240
257
 
241
258
  it( 'should use registered grouping block for grouping interactions', async () => {
242
- // Set custom Block as the Block to use for Grouping
259
+ // Set custom Block as the Block to use for Grouping.
243
260
  await page.evaluate( () => {
244
261
  window.wp.blocks.setGroupingBlockName(
245
262
  'test/alternative-group-block'
246
263
  );
247
264
  } );
248
265
 
249
- // Creating test blocks
266
+ // Creating test blocks.
250
267
  await insertBlocksOfSameType();
251
268
 
252
269
  // Multiselect via keyboard.
@@ -129,7 +129,7 @@ describe( 'Navigating the block hierarchy', () => {
129
129
  await page.keyboard.press( 'Enter' );
130
130
  await page.waitForSelector( '.is-selected[data-type="core/column"]' );
131
131
 
132
- // Insert text in the last column block
132
+ // Insert text in the last column block.
133
133
  await page.keyboard.press( 'ArrowDown' ); // Navigate to inserter.
134
134
  await page.keyboard.press( 'Enter' ); // Activate inserter.
135
135
  await page.keyboard.type( 'Paragraph' );
@@ -165,7 +165,7 @@ describe( 'Navigating the block hierarchy', () => {
165
165
  } );
166
166
 
167
167
  it( 'should select the wrapper div for a group', async () => {
168
- // Insert a group block
168
+ // Insert a group block.
169
169
  await insertBlock( 'Group' );
170
170
 
171
171
  // Insert some random blocks.
@@ -178,13 +178,13 @@ describe( 'Navigating the block hierarchy', () => {
178
178
  await page.keyboard.type( 'just a paragraph' );
179
179
  await insertBlock( 'Separator' );
180
180
 
181
- // Check the Group block content
181
+ // Check the Group block content.
182
182
  expect( await getEditedPostContent() ).toMatchSnapshot();
183
183
 
184
- // Unselect the blocks
184
+ // Unselect the blocks.
185
185
  await page.click( '.editor-post-title' );
186
186
 
187
- // Try selecting the group block using the Outline
187
+ // Try selecting the group block using the Outline.
188
188
  await page.click( '.edit-post-header-toolbar__list-view-toggle' );
189
189
  const groupMenuItem = (
190
190
  await page.$x(
@@ -320,13 +320,13 @@ describe( 'Change detection', () => {
320
320
  await clickBlockAppender();
321
321
  await page.keyboard.type( 'Paragraph' );
322
322
 
323
- // Save
323
+ // Save.
324
324
  await saveDraft();
325
325
 
326
326
  // Verify that the title is empty.
327
327
  const title = await page.$eval(
328
328
  '.editor-post-title__input',
329
- // Trim padding non-breaking space
329
+ // Trim padding non-breaking space.
330
330
  ( element ) => element.textContent.trim()
331
331
  );
332
332
  expect( title ).toBe( '' );
@@ -339,7 +339,7 @@ describe( 'Change detection', () => {
339
339
  // Enter title.
340
340
  await page.type( '.editor-post-title__input', 'Hello World' );
341
341
 
342
- // Save
342
+ // Save.
343
343
  await saveDraft();
344
344
  const postId = await page.evaluate( () =>
345
345
  window.wp.data.select( 'core/editor' ).getCurrentPostId()
@@ -28,7 +28,7 @@ describe( 'Compatibility with classic editor', () => {
28
28
  await viewPostLinks[ 0 ].click();
29
29
  await page.waitForNavigation();
30
30
 
31
- // Check the the content doesn't contain <p> tags
31
+ // Check the the content doesn't contain <p> tags.
32
32
  await page.waitForSelector( '.entry-content' );
33
33
  const content = await page.$eval( '.entry-content', ( element ) =>
34
34
  element.innerHTML.trim()