@wordpress/e2e-tests 6.5.0 → 7.0.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,12 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 7.0.0 (2023-03-15)
6
+
7
+ ### Breaking Changes
8
+
9
+ - Started requiring Jest v29 instead of v27 as a peer dependency. See [breaking changes in Jest 28](https://jestjs.io/blog/2022/04/25/jest-28) and [in jest 29](https://jestjs.io/blog/2022/08/25/jest-29) ([#47388](https://github.com/WordPress/gutenberg/pull/47388))
10
+
5
11
  ## 6.5.0 (2023-03-01)
6
12
 
7
13
  ## 6.4.0 (2023-02-15)
@@ -0,0 +1,7 @@
1
+ module.exports = ( api ) => {
2
+ api.cache( true );
3
+
4
+ return {
5
+ presets: [ '@wordpress/babel-preset-default' ],
6
+ };
7
+ };
@@ -26,24 +26,24 @@ async function setupPage() {
26
26
  ] );
27
27
  }
28
28
 
29
- // Before every test suite run, delete all content created by the test. This ensures
30
- // other posts/comments/etc. aren't dirtying tests and tests don't depend on
31
- // each other's side-effects.
29
+ // Before every test suite run, delete all content created by the test. This
30
+ // ensures other posts/comments/etc. aren't dirtying tests and tests don't
31
+ // depend on each other's side-effects.
32
32
  beforeAll( async () => {
33
33
  enablePageDialogAccept();
34
34
 
35
35
  await trashAllPosts();
36
36
  await trashAllPosts( 'wp_block' );
37
+ await activatePlugin( 'gutenberg-test-plugin-disables-the-css-animations' );
37
38
  await clearLocalStorage();
38
39
  await setupPage();
39
- await activatePlugin( 'gutenberg-test-plugin-disables-the-css-animations' );
40
40
  } );
41
41
 
42
42
  afterEach( async () => {
43
43
  // Clear localStorage between tests so that the next test starts clean.
44
44
  await clearLocalStorage();
45
- // Close the previous page entirely and create a new page, so that the next test
46
- // isn't affected by page unload work.
45
+ // Close the previous page entirely and create a new page, so that the next
46
+ // test isn't affected by page unload work.
47
47
  await page.close();
48
48
  page = await browser.newPage();
49
49
  // Set up testing config on new page.
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { get } from 'lodash';
5
4
  import { toMatchInlineSnapshot, toMatchSnapshot } from 'jest-snapshot';
6
5
 
7
6
  /**
@@ -172,11 +171,7 @@ function observeConsoleLogging() {
172
171
  // correctly. Instead, the logic here synchronously inspects the
173
172
  // internal object shape of the JSHandle to find the error text. If it
174
173
  // cannot be found, the default text value is used instead.
175
- text = get(
176
- message.args(),
177
- [ 0, '_remoteObject', 'description' ],
178
- text
179
- );
174
+ text = message.args()[ 0 ]?._remoteObject?.description ?? text;
180
175
 
181
176
  // Disable reason: We intentionally bubble up the console message
182
177
  // which, unless the test explicitly anticipates the logging via
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/e2e-tests",
3
- "version": "6.5.0",
3
+ "version": "7.0.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,22 +23,21 @@
23
23
  "node": ">=14"
24
24
  },
25
25
  "dependencies": {
26
- "@wordpress/e2e-test-utils": "^9.5.0",
27
- "@wordpress/jest-console": "^6.11.0",
28
- "@wordpress/jest-puppeteer-axe": "^5.11.0",
29
- "@wordpress/scripts": "^25.5.0",
30
- "@wordpress/url": "^3.29.0",
26
+ "@wordpress/e2e-test-utils": "^10.0.0",
27
+ "@wordpress/jest-console": "^7.0.0",
28
+ "@wordpress/jest-puppeteer-axe": "^6.0.0",
29
+ "@wordpress/scripts": "^26.0.0",
30
+ "@wordpress/url": "^3.30.0",
31
31
  "chalk": "^4.0.0",
32
32
  "expect-puppeteer": "^4.4.0",
33
33
  "filenamify": "^4.2.0",
34
- "jest-message-util": "^27.4.2",
35
- "jest-snapshot": "^27.4.5",
36
- "lodash": "^4.17.21",
34
+ "jest-message-util": "^29.5.0",
35
+ "jest-snapshot": "^29.5.0",
37
36
  "puppeteer-testing-library": "^0.5.0",
38
37
  "uuid": "^8.3.0"
39
38
  },
40
39
  "peerDependencies": {
41
- "jest": ">=27",
40
+ "jest": ">=29",
42
41
  "puppeteer-core": ">=11",
43
42
  "react": "^18.0.0",
44
43
  "react-dom": "^18.0.0"
@@ -46,5 +45,5 @@
46
45
  "publishConfig": {
47
46
  "access": "public"
48
47
  },
49
- "gitHead": "d5e03a74b79e3ca84afda24375474a103a063ee4"
48
+ "gitHead": "9534a7b3bbf07c1d40b94fdb7a3d091f297bfb06"
50
49
  }
@@ -88,7 +88,7 @@ exports[`Inserting blocks inserts a block in proper place after having clicked \
88
88
  <p>First paragraph</p>
89
89
  <!-- /wp:paragraph -->
90
90
 
91
- <!-- wp:cover {"isDark":false} -->
91
+ <!-- wp:cover {"isDark":false,"layout":{"type":"constrained"}} -->
92
92
  <div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-background-dim-100 has-background-dim"></span><div class="wp-block-cover__inner-container"></div></div>
93
93
  <!-- /wp:cover -->
94
94
 
@@ -58,9 +58,11 @@ describe( 'Navigating the block hierarchy', () => {
58
58
  // Add a paragraph in the first column.
59
59
  await page.keyboard.press( 'ArrowDown' ); // Navigate to inserter.
60
60
  await page.keyboard.press( 'Enter' ); // Activate inserter.
61
- await page.keyboard.type( 'Paragraph' );
62
- await pressKeyTimes( 'Tab', 2 ); // Tab to paragraph result.
63
- await page.keyboard.press( 'Enter' ); // Insert paragraph.
61
+ // Wait for inserter results to appear and then insert a paragraph.
62
+ await page.waitForSelector(
63
+ '.block-editor-inserter__quick-inserter-results .editor-block-list-item-paragraph'
64
+ );
65
+ await page.click( '.editor-block-list-item-paragraph' );
64
66
  await page.keyboard.type( 'First column' );
65
67
 
66
68
  // Navigate to the columns blocks.
@@ -99,9 +101,11 @@ describe( 'Navigating the block hierarchy', () => {
99
101
  // Insert text in the last column block.
100
102
  await page.keyboard.press( 'ArrowDown' ); // Navigate to inserter.
101
103
  await page.keyboard.press( 'Enter' ); // Activate inserter.
102
- await page.keyboard.type( 'Paragraph' );
103
- await pressKeyTimes( 'Tab', 2 ); // Tab to paragraph result.
104
- await page.keyboard.press( 'Enter' ); // Insert paragraph.
104
+ // Wait for inserter results to appear and then insert a paragraph.
105
+ await page.waitForSelector(
106
+ '.block-editor-inserter__quick-inserter-results .editor-block-list-item-paragraph'
107
+ );
108
+ await page.click( '.editor-block-list-item-paragraph' );
105
109
  await page.keyboard.type( 'Third column' );
106
110
 
107
111
  expect( await getEditedPostContent() ).toMatchSnapshot();
@@ -115,9 +119,11 @@ describe( 'Navigating the block hierarchy', () => {
115
119
  // Add a paragraph in the first column.
116
120
  await page.keyboard.press( 'ArrowDown' ); // Navigate to inserter.
117
121
  await page.keyboard.press( 'Enter' ); // Activate inserter.
118
- await page.keyboard.type( 'Paragraph' );
119
- await pressKeyTimes( 'Tab', 2 ); // Tab to paragraph result.
120
- await page.keyboard.press( 'Enter' ); // Insert paragraph.
122
+ // Wait for inserter results to appear and then insert a paragraph.
123
+ await page.waitForSelector(
124
+ '.block-editor-inserter__quick-inserter-results .editor-block-list-item-paragraph'
125
+ );
126
+ await page.click( '.editor-block-list-item-paragraph' );
121
127
  await page.keyboard.type( 'First column' );
122
128
 
123
129
  // Navigate to the columns blocks using the keyboard.
@@ -146,9 +152,11 @@ describe( 'Navigating the block hierarchy', () => {
146
152
  // Insert text in the last column block.
147
153
  await page.keyboard.press( 'ArrowDown' ); // Navigate to inserter.
148
154
  await page.keyboard.press( 'Enter' ); // Activate inserter.
149
- await page.keyboard.type( 'Paragraph' );
150
- await pressKeyTimes( 'Tab', 2 ); // Tab to paragraph result.
151
- await page.keyboard.press( 'Enter' ); // Insert paragraph.
155
+ // Wait for inserter results to appear and then insert a paragraph.
156
+ await page.waitForSelector(
157
+ '.block-editor-inserter__quick-inserter-results .editor-block-list-item-paragraph'
158
+ );
159
+ await page.click( '.editor-block-list-item-paragraph' );
152
160
  await page.keyboard.type( 'Third column' );
153
161
 
154
162
  expect( await getEditedPostContent() ).toMatchSnapshot();
@@ -412,13 +412,13 @@ describe( 'RichText', () => {
412
412
  await page.waitForXPath(
413
413
  '//button[@role="tab"][@aria-selected="true"][text()="Text"]'
414
414
  );
415
- // Tab to the "Text" tab.
415
+ // Initial focus is on the "Text" tab.
416
+ // Tab to the "Custom color picker".
416
417
  await page.keyboard.press( 'Tab' );
417
418
  // Tab to black.
418
419
  await page.keyboard.press( 'Tab' );
419
420
  // Select color other than black.
420
421
  await page.keyboard.press( 'Tab' );
421
- await page.keyboard.press( 'Tab' );
422
422
  await page.keyboard.press( 'Enter' );
423
423
 
424
424
  expect( await getEditedPostContent() ).toMatchSnapshot();
@@ -26,6 +26,7 @@ import {
26
26
  deleteFile,
27
27
  getTypingEventDurations,
28
28
  getLoadingDurations,
29
+ sequence,
29
30
  } from './utils';
30
31
 
31
32
  jest.setTimeout( 1000000 );
@@ -46,7 +47,7 @@ const results = {
46
47
  listViewOpen: [],
47
48
  };
48
49
 
49
- let id;
50
+ let postId;
50
51
 
51
52
  describe( 'Site Editor Performance', () => {
52
53
  beforeAll( async () => {
@@ -59,6 +60,7 @@ describe( 'Site Editor Performance', () => {
59
60
  );
60
61
 
61
62
  await createNewPost( { postType: 'page' } );
63
+
62
64
  await page.evaluate( ( _html ) => {
63
65
  const { parse } = window.wp.blocks;
64
66
  const { dispatch } = window.wp.data;
@@ -75,48 +77,47 @@ describe( 'Site Editor Performance', () => {
75
77
  }, html );
76
78
  await saveDraft();
77
79
 
78
- id = await page.evaluate( () =>
80
+ postId = await page.evaluate( () =>
79
81
  new URL( document.location ).searchParams.get( 'post' )
80
82
  );
81
83
  } );
82
84
 
83
85
  afterAll( async () => {
86
+ const resultsFilename = basename( __filename, '.js' ) + '.results.json';
87
+ writeFileSync(
88
+ join( __dirname, resultsFilename ),
89
+ JSON.stringify( results, null, 2 )
90
+ );
91
+
84
92
  await deleteAllTemplates( 'wp_template' );
85
93
  await deleteAllTemplates( 'wp_template_part' );
86
94
  await activateTheme( 'twentytwentyone' );
87
95
  } );
88
96
 
89
- beforeEach( async () => {
90
- await visitSiteEditor( {
91
- postId: id,
92
- postType: 'page',
93
- } );
94
- } );
95
-
96
- it( 'Loading', async () => {
97
- const editorURL = await page.url();
98
-
99
- // Number of sample measurements to take.
100
- const samples = 3;
101
- // Number of throwaway measurements to perform before recording samples.
102
- // Having at least one helps ensure that caching quirks don't manifest in
103
- // the results.
104
- const throwaway = 1;
105
-
106
- let i = throwaway + samples;
107
-
108
- // Measuring loading time.
109
- while ( i-- ) {
110
- await page.close();
111
- page = await browser.newPage();
112
-
113
- await page.goto( editorURL );
114
- await page.waitForSelector( '.edit-site-visual-editor', {
115
- timeout: 120000,
97
+ // Number of loading measurements to take.
98
+ const loadingSamples = 3;
99
+ // Number of throwaway measurements to perform before recording samples.
100
+ // Having at least one helps ensure that caching quirks don't manifest
101
+ // in the results.
102
+ const loadingSamplesThrowaway = 1;
103
+ const loadingIterations = sequence(
104
+ 1,
105
+ loadingSamples + loadingSamplesThrowaway
106
+ );
107
+ it.each( loadingIterations )(
108
+ `Loading (%i of ${ loadingIterations.length })`,
109
+ async ( i ) => {
110
+ // Open the test page in Site Editor.
111
+ await visitSiteEditor( {
112
+ postId,
113
+ postType: 'page',
116
114
  } );
117
- await canvas().waitForSelector( '.wp-block', { timeout: 120000 } );
118
115
 
119
- if ( i < samples ) {
116
+ // Wait for the first block.
117
+ await canvas().waitForSelector( '.wp-block' );
118
+
119
+ // Save results.
120
+ if ( i > loadingSamplesThrowaway ) {
120
121
  const {
121
122
  serverResponse,
122
123
  firstPaint,
@@ -133,52 +134,53 @@ describe( 'Site Editor Performance', () => {
133
134
  results.firstContentfulPaint.push( firstContentfulPaint );
134
135
  results.firstBlock.push( firstBlock );
135
136
  }
137
+
138
+ expect( true ).toBe( true );
136
139
  }
137
- } );
140
+ );
138
141
 
139
142
  it( 'Typing', async () => {
140
- await page.waitForSelector( '.edit-site-visual-editor', {
141
- timeout: 120000,
143
+ // Open the test page in Site Editor.
144
+ await visitSiteEditor( {
145
+ postId,
146
+ postType: 'page',
142
147
  } );
143
- await canvas().waitForSelector( '.wp-block', { timeout: 120000 } );
144
148
 
145
- // Measuring typing performance inside the post content.
146
- await canvas().waitForSelector(
147
- '[data-type="core/post-content"] [data-type="core/paragraph"]'
149
+ // Wait for the first paragraph to be ready.
150
+ const firstParagraph = await canvas().waitForXPath(
151
+ '//p[contains(text(), "Lorem ipsum dolor sit amet")]'
148
152
  );
153
+
154
+ // Get inside the post content.
149
155
  await enterEditMode();
150
- await canvas().focus(
151
- '[data-type="core/post-content"] [data-type="core/paragraph"]'
152
- );
156
+
157
+ // Insert a new paragraph right under the first one.
158
+ await firstParagraph.focus();
153
159
  await insertBlock( 'Paragraph' );
154
- let i = 200;
160
+
161
+ // Start tracing.
155
162
  const traceFile = __dirname + '/trace.json';
156
163
  await page.tracing.start( {
157
164
  path: traceFile,
158
165
  screenshots: false,
159
166
  categories: [ 'devtools.timeline' ],
160
167
  } );
161
- while ( i-- ) {
162
- await page.keyboard.type( 'x' );
163
- }
168
+
169
+ // Type "x" 200 times.
170
+ await page.keyboard.type( new Array( 200 ).fill( 'x' ).join( '' ) );
171
+
172
+ // Stop tracing and save results.
164
173
  await page.tracing.stop();
165
174
  const traceResults = JSON.parse( readFile( traceFile ) );
166
175
  const [ keyDownEvents, keyPressEvents, keyUpEvents ] =
167
176
  getTypingEventDurations( traceResults );
168
-
169
- for ( let j = 0; j < keyDownEvents.length; j++ ) {
177
+ for ( let i = 0; i < keyDownEvents.length; i++ ) {
170
178
  results.type.push(
171
- keyDownEvents[ j ] + keyPressEvents[ j ] + keyUpEvents[ j ]
179
+ keyDownEvents[ i ] + keyPressEvents[ i ] + keyUpEvents[ i ]
172
180
  );
173
181
  }
174
182
 
175
- const resultsFilename = basename( __filename, '.js' ) + '.results.json';
176
-
177
- writeFileSync(
178
- join( __dirname, resultsFilename ),
179
- JSON.stringify( results, null, 2 )
180
- );
181
-
183
+ // Delete the original trace file.
182
184
  deleteFile( traceFile );
183
185
 
184
186
  expect( true ).toBe( true );
@@ -124,3 +124,7 @@ export async function getLoadingDurations() {
124
124
  export function sum( arr ) {
125
125
  return arr.reduce( ( a, b ) => a + b, 0 );
126
126
  }
127
+
128
+ export function sequence( start, length ) {
129
+ return Array.from( { length }, ( _, i ) => i + start );
130
+ }
@@ -75,11 +75,13 @@ describe( 'Settings sidebar', () => {
75
75
 
76
76
  expect( templateCardBeforeNavigation ).toMatchObject( {
77
77
  title: 'Index',
78
- description: 'Displays posts.',
78
+ description:
79
+ 'Used as a fallback template for all pages when a more specific template is not defined.',
79
80
  } );
80
81
  expect( templateCardAfterNavigation ).toMatchObject( {
81
82
  title: 'Singular',
82
- description: 'Displays a single post or page.',
83
+ description:
84
+ 'Displays any single entry, such as a post or a page. This template will serve as a fallback when a more specific template (e.g., Single Post, Page, or Attachment) cannot be found.',
83
85
  } );
84
86
  } );
85
87
  } );
@@ -24,7 +24,6 @@ import {
24
24
  */
25
25
  // eslint-disable-next-line no-restricted-imports
26
26
  import { find, findAll } from 'puppeteer-testing-library';
27
- import { groupBy, mapValues } from 'lodash';
28
27
 
29
28
  describe( 'Widgets screen', () => {
30
29
  beforeEach( async () => {
@@ -945,13 +944,20 @@ async function saveWidgets() {
945
944
  async function getSerializedWidgetAreas() {
946
945
  const widgets = await rest( { path: '/wp/v2/widgets' } );
947
946
 
948
- const serializedWidgetAreas = mapValues(
949
- groupBy( widgets, 'sidebar' ),
950
- ( sidebarWidgets ) =>
951
- sidebarWidgets
952
- .map( ( widget ) => widget.rendered )
953
- .filter( Boolean )
954
- .join( '\n' )
947
+ const serializedWidgetAreas = widgets.reduce(
948
+ ( acc, { sidebar, rendered } ) => {
949
+ const currentWidgets = acc[ sidebar ] || '';
950
+ let newWidgets = Boolean( rendered ) ? rendered : '';
951
+ if ( currentWidgets.length && newWidgets.length ) {
952
+ newWidgets = '\n' + newWidgets;
953
+ }
954
+
955
+ return {
956
+ ...acc,
957
+ [ sidebar ]: currentWidgets + newWidgets,
958
+ };
959
+ },
960
+ {}
955
961
  );
956
962
 
957
963
  return serializedWidgetAreas;