@wordpress/e2e-tests 7.18.0 → 7.19.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 7.19.0 (2023-12-13)
6
+
5
7
  ## 7.18.0 (2023-11-29)
6
8
 
7
9
  ## 7.17.0 (2023-11-16)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/e2e-tests",
3
- "version": "7.18.0",
3
+ "version": "7.19.0",
4
4
  "description": "End-To-End (E2E) tests for WordPress.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -23,12 +23,12 @@
23
23
  "node": ">=14"
24
24
  },
25
25
  "dependencies": {
26
- "@wordpress/e2e-test-utils": "^10.18.0",
27
- "@wordpress/interactivity": "^3.0.0",
28
- "@wordpress/jest-console": "^7.18.0",
29
- "@wordpress/jest-puppeteer-axe": "^6.18.0",
30
- "@wordpress/scripts": "^26.18.0",
31
- "@wordpress/url": "^3.48.0",
26
+ "@wordpress/e2e-test-utils": "^10.19.0",
27
+ "@wordpress/interactivity": "^3.1.0",
28
+ "@wordpress/jest-console": "^7.19.0",
29
+ "@wordpress/jest-puppeteer-axe": "^6.19.0",
30
+ "@wordpress/scripts": "^26.19.0",
31
+ "@wordpress/url": "^3.49.0",
32
32
  "chalk": "^4.0.0",
33
33
  "expect-puppeteer": "^4.4.0",
34
34
  "filenamify": "^4.2.0",
@@ -46,5 +46,5 @@
46
46
  "publishConfig": {
47
47
  "access": "public"
48
48
  },
49
- "gitHead": "d98dff8ea96f29cfea045bf964269f46f040d539"
49
+ "gitHead": "fcf61b4beff747222c2c81d09d757ca1a0abd925"
50
50
  }
@@ -3,6 +3,7 @@
3
3
  * HTML for testing the router navigate function.
4
4
  *
5
5
  * @package gutenberg-test-interactive-blocks
6
+ *
6
7
  * @phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
7
8
  */
8
9
 
@@ -3,6 +3,7 @@
3
3
  * HTML for testing the hydration of router regions.
4
4
  *
5
5
  * @package gutenberg-test-interactive-blocks
6
+ *
6
7
  * @phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
7
8
  */
8
9
 
@@ -3,6 +3,7 @@
3
3
  * HTML for testing the hydration of the serialized store.
4
4
  *
5
5
  * @package gutenberg-test-interactive-blocks
6
+ *
6
7
  * @phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
7
8
  */
8
9
 
@@ -370,7 +370,11 @@ describe( 'Change detection', () => {
370
370
  it( 'consecutive edits to the same attribute should mark the post as dirty after a save', async () => {
371
371
  // Open the sidebar block settings.
372
372
  await openDocumentSettingsSidebar();
373
- await page.click( '.edit-post-sidebar__panel-tab[data-label="Block"]' );
373
+
374
+ const blockInspectorTab = await page.waitForXPath(
375
+ '//button[@role="tab"][contains(text(), "Block")]'
376
+ );
377
+ await blockInspectorTab.click();
374
378
 
375
379
  // Insert a paragraph.
376
380
  await clickBlockAppender();
@@ -102,21 +102,24 @@ describe( 'Editing modes (visual/HTML)', () => {
102
102
  expect( title ).toBe( 'Paragraph' );
103
103
 
104
104
  // The Block inspector should be active.
105
- let blockInspectorTab = await page.$(
106
- '.edit-post-sidebar__panel-tab.is-active[data-label="Block"]'
105
+ let [ blockInspectorTab ] = await page.$x(
106
+ '//button[@role="tab"][@aria-selected="true"][contains(text(), "Block")]'
107
107
  );
108
108
  expect( blockInspectorTab ).not.toBeNull();
109
109
 
110
110
  await switchEditorModeTo( 'Code' );
111
111
 
112
112
  // The Block inspector should not be active anymore.
113
- blockInspectorTab = await page.$(
114
- '.edit-post-sidebar__panel-tab.is-active[data-label="Block"]'
113
+ [ blockInspectorTab ] = await page.$x(
114
+ '//button[@role="tab"][@aria-selected="true"][contains(text(), "Block")]'
115
115
  );
116
- expect( blockInspectorTab ).toBeNull();
116
+ expect( blockInspectorTab ).toBeUndefined();
117
117
 
118
118
  // No block is selected.
119
- await page.click( '.edit-post-sidebar__panel-tab[data-label="Block"]' );
119
+ const inactiveBlockInspectorTab = await page.waitForXPath(
120
+ '//button[@role="tab"][contains(text(), "Block")]'
121
+ );
122
+ inactiveBlockInspectorTab.click();
120
123
  const noBlocksElement = await page.$(
121
124
  '.block-editor-block-inspector__no-blocks'
122
125
  );
@@ -17,7 +17,7 @@ describe( 'preferences', () => {
17
17
  async function getActiveSidebarTabText() {
18
18
  try {
19
19
  return await page.$eval(
20
- '.edit-post-sidebar__panel-tab.is-active',
20
+ 'div[aria-label="Editor settings"] [role="tab"][aria-selected="true"]',
21
21
  ( node ) => node.textContent
22
22
  );
23
23
  } catch ( error ) {
@@ -29,11 +29,15 @@ describe( 'preferences', () => {
29
29
  }
30
30
 
31
31
  it( 'remembers sidebar dismissal between sessions', async () => {
32
+ const blockTab = await page.waitForXPath(
33
+ `//button[@role="tab"][contains(text(), 'Block')]`
34
+ );
35
+
32
36
  // Open by default.
33
37
  expect( await getActiveSidebarTabText() ).toBe( 'Post' );
34
38
 
35
39
  // Change to "Block" tab.
36
- await page.click( '.edit-post-sidebar__panel-tab[aria-label="Block"]' );
40
+ await blockTab.click();
37
41
  expect( await getActiveSidebarTabText() ).toBe( 'Block' );
38
42
 
39
43
  // Regression test: Reload resets to document tab.
@@ -46,7 +50,7 @@ describe( 'preferences', () => {
46
50
 
47
51
  // Dismiss.
48
52
  await page.click(
49
- '.edit-post-sidebar__panel-tabs [aria-label="Close Settings"]'
53
+ 'div[aria-label="Editor settings"] div[role="tablist"] + button[aria-label="Close Settings"]'
50
54
  );
51
55
  expect( await getActiveSidebarTabText() ).toBe( null );
52
56
 
@@ -13,7 +13,8 @@ import {
13
13
  } from '@wordpress/e2e-test-utils';
14
14
 
15
15
  const SIDEBAR_SELECTOR = '.edit-post-sidebar';
16
- const ACTIVE_SIDEBAR_TAB_SELECTOR = '.edit-post-sidebar__panel-tab.is-active';
16
+ const ACTIVE_SIDEBAR_TAB_SELECTOR =
17
+ 'div[aria-label="Editor settings"] [role="tab"][aria-selected="true"]';
17
18
  const ACTIVE_SIDEBAR_BUTTON_TEXT = 'Post';
18
19
 
19
20
  describe( 'Sidebar', () => {
@@ -99,22 +100,24 @@ describe( 'Sidebar', () => {
99
100
 
100
101
  // Tab lands at first (presumed selected) option "Post".
101
102
  await page.keyboard.press( 'Tab' );
102
- const isActiveDocumentTab = await page.evaluate(
103
- () =>
104
- document.activeElement.textContent === 'Post' &&
105
- document.activeElement.classList.contains( 'is-active' )
103
+
104
+ // The Post tab should be focused and selected.
105
+ const [ documentInspectorTab ] = await page.$x(
106
+ '//button[@role="tab"][@aria-selected="true"][contains(text(), "Post")]'
106
107
  );
107
- expect( isActiveDocumentTab ).toBe( true );
108
+ expect( documentInspectorTab ).toBeDefined();
109
+ expect( documentInspectorTab ).toHaveFocus();
108
110
 
109
- // Tab into and activate "Block".
110
- await page.keyboard.press( 'Tab' );
111
+ // Arrow key into and activate "Block".
112
+ await page.keyboard.press( 'ArrowRight' );
111
113
  await page.keyboard.press( 'Space' );
112
- const isActiveBlockTab = await page.evaluate(
113
- () =>
114
- document.activeElement.textContent === 'Block' &&
115
- document.activeElement.classList.contains( 'is-active' )
114
+
115
+ // The Block tab should be focused and selected.
116
+ const [ blockInspectorTab ] = await page.$x(
117
+ '//button[@role="tab"][@aria-selected="true"][contains(text(), "Block")]'
116
118
  );
117
- expect( isActiveBlockTab ).toBe( true );
119
+ expect( blockInspectorTab ).toBeDefined();
120
+ expect( blockInspectorTab ).toHaveFocus();
118
121
  } );
119
122
 
120
123
  it( 'should be possible to programmatically remove Document Settings panels', async () => {
@@ -1,56 +0,0 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import {
5
- activatePlugin,
6
- createNewPost,
7
- deactivatePlugin,
8
- insertBlock,
9
- createEmbeddingMatcher,
10
- createJSONResponse,
11
- setUpResponseMocking,
12
- } from '@wordpress/e2e-test-utils';
13
-
14
- const MOCK_RESPONSES = [
15
- {
16
- match: createEmbeddingMatcher( 'https://twitter.com/wordpress' ),
17
- onRequestMatch: createJSONResponse( {
18
- url: 'https://twitter.com/wordpress',
19
- html: '<p>Mock success response.</p>',
20
- type: 'rich',
21
- provider_name: 'Twitter',
22
- provider_url: 'https://twitter.com',
23
- version: '1.0',
24
- } ),
25
- },
26
- ];
27
-
28
- describe( 'Embed block inside a locked all parent', () => {
29
- beforeAll( async () => {
30
- await activatePlugin( 'gutenberg-test-innerblocks-locking-all-embed' );
31
- } );
32
-
33
- beforeEach( async () => {
34
- await setUpResponseMocking( MOCK_RESPONSES );
35
- await createNewPost();
36
- } );
37
-
38
- afterAll( async () => {
39
- await deactivatePlugin(
40
- 'gutenberg-test-innerblocks-locking-all-embed'
41
- );
42
- } );
43
-
44
- it( 'embed block should be able to embed external content', async () => {
45
- await insertBlock( 'Test Inner Blocks Locking All Embed' );
46
- const embedInputSelector =
47
- '.components-placeholder__input[aria-label="Embed URL"]';
48
- await page.waitForSelector( embedInputSelector );
49
- await page.click( embedInputSelector );
50
- // This URL should not have a trailing slash.
51
- await page.keyboard.type( 'https://twitter.com/wordpress' );
52
- await page.keyboard.press( 'Enter' );
53
- // The twitter block should appear correctly.
54
- await page.waitForSelector( 'figure.wp-block-embed' );
55
- } );
56
- } );
@@ -1,239 +0,0 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import {
5
- createNewPost,
6
- disablePrePublishChecks,
7
- getOption,
8
- insertBlock,
9
- publishPost,
10
- setOption,
11
- trashAllPosts,
12
- activateTheme,
13
- clickButton,
14
- createReusableBlock,
15
- deleteAllTemplates,
16
- canvas,
17
- } from '@wordpress/e2e-test-utils';
18
-
19
- describe( 'Multi-entity save flow', () => {
20
- // Selectors - usable between Post/Site editors.
21
- const checkedBoxSelector = '.components-checkbox-control__checked';
22
- const checkboxInputSelector = '.components-checkbox-control__input';
23
- const entitiesSaveSelector = '.editor-entities-saved-states__save-button';
24
- const savePanelSelector = '.entities-saved-states__panel';
25
- const closePanelButtonSelector =
26
- '.editor-post-publish-panel__header-cancel-button button:not(:disabled)';
27
-
28
- // Reusable assertions across Post/Site editors.
29
- const assertAllBoxesChecked = async () => {
30
- const checkedBoxes = await page.$$( checkedBoxSelector );
31
- const checkboxInputs = await page.$$( checkboxInputSelector );
32
- expect( checkedBoxes.length - checkboxInputs.length ).toBe( 0 );
33
- };
34
- const assertExistence = async ( selector, shouldBePresent ) => {
35
- const element = await page.$( selector );
36
- if ( shouldBePresent ) {
37
- expect( element ).not.toBeNull();
38
- } else {
39
- expect( element ).toBeNull();
40
- }
41
- };
42
-
43
- let originalSiteTitle, originalBlogDescription;
44
-
45
- beforeAll( async () => {
46
- await activateTheme( 'emptytheme' );
47
- await deleteAllTemplates( 'wp_template' );
48
- await deleteAllTemplates( 'wp_template_part' );
49
- await trashAllPosts( 'wp_block' );
50
-
51
- // Get the current Site Title and Site Tagline, so that we can reset
52
- // them back to the original values once the test suite has finished.
53
- originalSiteTitle = await getOption( 'blogname' );
54
- originalBlogDescription = await getOption( 'blogdescription' );
55
- } );
56
-
57
- afterAll( async () => {
58
- await activateTheme( 'twentytwentyone' );
59
-
60
- // Reset the Site Title and Site Tagline back to their original values.
61
- await setOption( 'blogname', originalSiteTitle );
62
- await setOption( 'blogdescription', originalBlogDescription );
63
- } );
64
-
65
- describe( 'Post Editor', () => {
66
- // Selectors - Post editor specific.
67
- const draftSavedSelector = '.editor-post-saved-state.is-saved';
68
- const multiSaveSelector =
69
- '.editor-post-publish-button__button.has-changes-dot';
70
- const savePostSelector = '.editor-post-publish-button__button';
71
- const enabledSavePostSelector = `${ savePostSelector }[aria-disabled=false]`;
72
- const publishA11ySelector =
73
- '.edit-post-layout__toggle-publish-panel-button';
74
- const saveA11ySelector =
75
- '.edit-post-layout__toggle-entities-saved-states-panel-button';
76
- const publishPanelSelector = '.editor-post-publish-panel';
77
-
78
- // Reusable assertions inside Post editor.
79
- const assertMultiSaveEnabled = async () => {
80
- const multiSaveButton =
81
- await page.waitForSelector( multiSaveSelector );
82
- expect( multiSaveButton ).not.toBeNull();
83
- };
84
- const assertMultiSaveDisabled = async () => {
85
- const multiSaveButton = await page.waitForSelector(
86
- multiSaveSelector,
87
- { hidden: true }
88
- );
89
- expect( multiSaveButton ).toBeNull();
90
- };
91
-
92
- it( 'Save flow should work as expected.', async () => {
93
- await createNewPost();
94
- // Edit the page some.
95
- await canvas().waitForSelector( '.editor-post-title' );
96
- await canvas().click( '.editor-post-title' );
97
- await page.keyboard.type( 'Test Post...' );
98
- await page.keyboard.press( 'Enter' );
99
-
100
- // Should not trigger multi-entity save button with only post edited.
101
- await assertMultiSaveDisabled();
102
-
103
- // Should only have publish panel a11y button active with only post edited.
104
- await assertExistence( publishA11ySelector, true );
105
- await assertExistence( saveA11ySelector, false );
106
- await assertExistence( publishPanelSelector, false );
107
- await assertExistence( savePanelSelector, false );
108
-
109
- // Add a reusable block and edit it.
110
- await createReusableBlock( 'Hi!', 'Test' );
111
- await canvas().waitForSelector( 'p[data-type="core/paragraph"]' );
112
- await canvas().click( 'p[data-type="core/paragraph"]' );
113
- await page.keyboard.type( 'Oh!' );
114
-
115
- // Should trigger multi-entity save button once template part edited.
116
- await assertMultiSaveEnabled();
117
-
118
- // Should only have save panel a11y button active after child entities edited.
119
- await assertExistence( publishA11ySelector, false );
120
- await assertExistence( saveA11ySelector, true );
121
- await assertExistence( publishPanelSelector, false );
122
- await assertExistence( savePanelSelector, false );
123
-
124
- // Opening panel has boxes checked by default.
125
- await page.click( savePostSelector );
126
- await page.waitForSelector( savePanelSelector );
127
- await assertAllBoxesChecked();
128
-
129
- // Should not show other panels (or their a11y buttons) while save panel opened.
130
- await assertExistence( publishA11ySelector, false );
131
- await assertExistence( saveA11ySelector, false );
132
- await assertExistence( publishPanelSelector, false );
133
-
134
- // Publish panel should open after saving.
135
- await page.click( entitiesSaveSelector );
136
- await page.waitForSelector( publishPanelSelector );
137
-
138
- // No other panels (or their a11y buttons) should be present with publish panel open.
139
- await assertExistence( publishA11ySelector, false );
140
- await assertExistence( saveA11ySelector, false );
141
- await assertExistence( savePanelSelector, false );
142
-
143
- // Close publish panel.
144
- const closePanelButton = await page.waitForSelector(
145
- closePanelButtonSelector
146
- );
147
- await closePanelButton.click();
148
-
149
- // Verify saving is disabled.
150
- const draftSaved = await page.waitForSelector( draftSavedSelector );
151
- expect( draftSaved ).not.toBeNull();
152
- await assertMultiSaveDisabled();
153
- await assertExistence( saveA11ySelector, false );
154
-
155
- await publishPost();
156
- // Wait for the success notice specifically for the published post.
157
- // `publishPost()` has a similar check but it only checks for the
158
- // existence of any snackbars. In this case, there's another "Site updated"
159
- // notice which will be sufficient for that and thus creating a false-positive.
160
- await page.waitForXPath(
161
- '//*[@id="a11y-speak-polite"][contains(text(), "Post published")]'
162
- );
163
-
164
- // Unselect the blocks to avoid clicking the block toolbar.
165
- await page.evaluate( () => {
166
- wp.data.dispatch( 'core/block-editor' ).clearSelectedBlock();
167
- } );
168
-
169
- // Update the post.
170
- await canvas().click( '.editor-post-title' );
171
- await page.keyboard.type( '...more title!' );
172
-
173
- // Verify update button is enabled.
174
- const enabledSaveButton = await page.waitForSelector(
175
- enabledSavePostSelector
176
- );
177
- expect( enabledSaveButton ).not.toBeNull();
178
- // Verify multi-entity saving not enabled.
179
- await assertMultiSaveDisabled();
180
- await assertExistence( saveA11ySelector, false );
181
-
182
- // Update reusable block again.
183
- await canvas().click( 'p[data-type="core/paragraph"]' );
184
- // We need to click again due to the clickthrough overlays in reusable blocks.
185
- await canvas().click( 'p[data-type="core/paragraph"]' );
186
- await page.keyboard.type( 'R!' );
187
-
188
- // Multi-entity saving should be enabled.
189
- await assertMultiSaveEnabled();
190
- await assertExistence( saveA11ySelector, true );
191
- } );
192
-
193
- it( 'Site blocks should save individually', async () => {
194
- await createNewPost();
195
- await disablePrePublishChecks();
196
-
197
- await insertBlock( 'Site Title' );
198
- // Ensure title is retrieved before typing.
199
- await page.waitForXPath(
200
- `//a[contains(text(), "${ originalSiteTitle }")]`
201
- );
202
- const editableSiteTitleSelector =
203
- '.wp-block-site-title a[contenteditable="true"]';
204
- await canvas().waitForSelector( editableSiteTitleSelector );
205
- await canvas().focus( editableSiteTitleSelector );
206
- await page.keyboard.type( '...' );
207
-
208
- await insertBlock( 'Site Tagline' );
209
- // Wait for the placeholder.
210
- await canvas().waitForXPath(
211
- '//span[@data-rich-text-placeholder="Write site tagline…"]'
212
- );
213
- const editableSiteTagLineSelector =
214
- '.wp-block-site-tagline[contenteditable="true"]';
215
- await canvas().waitForSelector( editableSiteTagLineSelector );
216
- await canvas().focus( editableSiteTagLineSelector );
217
- await page.keyboard.type( 'Just another WordPress site' );
218
-
219
- await clickButton( 'Publish' );
220
- await page.waitForSelector( savePanelSelector );
221
- let checkboxInputs = await page.$$( checkboxInputSelector );
222
- expect( checkboxInputs ).toHaveLength( 3 );
223
-
224
- await checkboxInputs[ 1 ].click();
225
- await page.click( entitiesSaveSelector );
226
-
227
- // Wait for the snackbar notice that the post has been published.
228
- await page.waitForSelector( '.components-snackbar' );
229
-
230
- await clickButton( 'Update…' );
231
- await page.waitForSelector( savePanelSelector );
232
-
233
- await page.waitForSelector( checkboxInputSelector );
234
- checkboxInputs = await page.$$( checkboxInputSelector );
235
-
236
- expect( checkboxInputs ).toHaveLength( 1 );
237
- } );
238
- } );
239
- } );
@@ -1,63 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import fs from 'fs';
5
- import path from 'path';
6
- import os from 'os';
7
-
8
- /**
9
- * WordPress dependencies
10
- */
11
- import {
12
- deleteAllTemplates,
13
- activateTheme,
14
- visitSiteEditor,
15
- enterEditMode,
16
- clickOnMoreMenuItem,
17
- } from '@wordpress/e2e-test-utils';
18
-
19
- async function waitForFileExists( filePath, timeout = 10000 ) {
20
- const start = Date.now();
21
- while ( ! fs.existsSync( filePath ) ) {
22
- // Puppeteer doesn't have an API for managing file downloads.
23
- // We are using `waitForTimeout` to add delays between check of file existence.
24
- // eslint-disable-next-line no-restricted-syntax
25
- await page.waitForTimeout( 1000 );
26
- if ( Date.now() - start > timeout ) {
27
- throw Error( 'waitForFileExists timeout' );
28
- }
29
- }
30
- }
31
-
32
- describe( 'Site Editor Templates Export', () => {
33
- beforeAll( async () => {
34
- await activateTheme( 'emptytheme' );
35
- await deleteAllTemplates( 'wp_template' );
36
- await deleteAllTemplates( 'wp_template_part' );
37
- } );
38
-
39
- afterAll( async () => {
40
- await activateTheme( 'twentytwentyone' );
41
- } );
42
-
43
- beforeEach( async () => {
44
- await visitSiteEditor();
45
- await enterEditMode();
46
- } );
47
-
48
- it( 'clicking export should download emptytheme.zip file', async () => {
49
- const directory = fs.mkdtempSync(
50
- path.join( os.tmpdir(), 'test-edit-site-export-' )
51
- );
52
- await page._client.send( 'Page.setDownloadBehavior', {
53
- behavior: 'allow',
54
- downloadPath: directory,
55
- } );
56
-
57
- await clickOnMoreMenuItem( 'Export', 'site-editor' );
58
- const filePath = path.join( directory, 'emptytheme.zip' );
59
- await waitForFileExists( filePath );
60
- expect( fs.existsSync( filePath ) ).toBe( true );
61
- fs.unlinkSync( filePath );
62
- } );
63
- } );