@wordpress/e2e-tests 4.3.0 → 4.4.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.
@@ -56,6 +56,7 @@ class FlakyTestsReporter {
56
56
  await fs.writeFile(
57
57
  `flaky-tests/${ filenamify( testTitle ) }.json`,
58
58
  JSON.stringify( {
59
+ version: 1,
59
60
  runner: 'jest-circus',
60
61
  title: testTitle,
61
62
  path: testPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/e2e-tests",
3
- "version": "4.3.0",
3
+ "version": "4.4.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,11 +23,11 @@
23
23
  "node": ">=12"
24
24
  },
25
25
  "dependencies": {
26
- "@wordpress/e2e-test-utils": "^7.5.0",
27
- "@wordpress/jest-console": "^5.1.0",
26
+ "@wordpress/e2e-test-utils": "^7.6.0",
27
+ "@wordpress/jest-console": "^5.2.0",
28
28
  "@wordpress/jest-puppeteer-axe": "^4.0.2",
29
- "@wordpress/scripts": "^23.1.0",
30
- "@wordpress/url": "^3.10.0",
29
+ "@wordpress/scripts": "^23.2.0",
30
+ "@wordpress/url": "^3.11.0",
31
31
  "chalk": "^4.0.0",
32
32
  "expect-puppeteer": "^4.4.0",
33
33
  "filenamify": "^4.2.0",
@@ -46,5 +46,5 @@
46
46
  "publishConfig": {
47
47
  "access": "public"
48
48
  },
49
- "gitHead": "198fa129cf1af8dc615918987ea6795cd40ab7df"
49
+ "gitHead": "a3e0b62091e8a8bdf5e2518e42d60d7098af48cc"
50
50
  }
@@ -3,7 +3,7 @@
3
3
  exports[`Buttons can jump to the link editor using the keyboard shortcut 1`] = `
4
4
  "<!-- wp:buttons -->
5
5
  <div class=\\"wp-block-buttons\\"><!-- wp:button -->
6
- <div class=\\"wp-block-button\\"><a class=\\"wp-block-button__link\\" href=\\"https://www.wordpress.org/\\">WordPress</a></div>
6
+ <div class=\\"wp-block-button\\"><a class=\\"wp-block-button__link wp-element-button\\" href=\\"https://www.wordpress.org/\\">WordPress</a></div>
7
7
  <!-- /wp:button --></div>
8
8
  <!-- /wp:buttons -->"
9
9
  `;
@@ -11,7 +11,7 @@ exports[`Buttons can jump to the link editor using the keyboard shortcut 1`] = `
11
11
  exports[`Buttons dismisses link editor when escape is pressed 1`] = `
12
12
  "<!-- wp:buttons -->
13
13
  <div class=\\"wp-block-buttons\\"><!-- wp:button -->
14
- <div class=\\"wp-block-button\\"><a class=\\"wp-block-button__link\\">WordPress</a></div>
14
+ <div class=\\"wp-block-button\\"><a class=\\"wp-block-button__link wp-element-button\\">WordPress</a></div>
15
15
  <!-- /wp:button --></div>
16
16
  <!-- /wp:buttons -->"
17
17
  `;
@@ -19,7 +19,7 @@ exports[`Buttons dismisses link editor when escape is pressed 1`] = `
19
19
  exports[`Buttons has focus on button content (slash inserter) 1`] = `
20
20
  "<!-- wp:buttons -->
21
21
  <div class=\\"wp-block-buttons\\"><!-- wp:button -->
22
- <div class=\\"wp-block-button\\"><a class=\\"wp-block-button__link\\">Content</a></div>
22
+ <div class=\\"wp-block-button\\"><a class=\\"wp-block-button__link wp-element-button\\">Content</a></div>
23
23
  <!-- /wp:button --></div>
24
24
  <!-- /wp:buttons -->"
25
25
  `;
@@ -27,7 +27,7 @@ exports[`Buttons has focus on button content (slash inserter) 1`] = `
27
27
  exports[`Buttons has focus on button content 1`] = `
28
28
  "<!-- wp:buttons -->
29
29
  <div class=\\"wp-block-buttons\\"><!-- wp:button -->
30
- <div class=\\"wp-block-button\\"><a class=\\"wp-block-button__link\\">Content</a></div>
30
+ <div class=\\"wp-block-button\\"><a class=\\"wp-block-button__link wp-element-button\\">Content</a></div>
31
31
  <!-- /wp:button --></div>
32
32
  <!-- /wp:buttons -->"
33
33
  `;
@@ -12,8 +12,6 @@ describe( 'Heading', () => {
12
12
  const COLOR_ITEM_SELECTOR =
13
13
  '.block-editor-panel-color-gradient-settings__dropdown';
14
14
  const CUSTOM_COLOR_BUTTON_X_SELECTOR = `.components-color-palette__custom-color`;
15
- const CUSTOM_COLOR_DETAILS_BUTTON_SELECTOR =
16
- '.components-color-picker button[aria-label="Show detailed inputs"]';
17
15
  const COLOR_INPUT_FIELD_SELECTOR =
18
16
  '.components-color-picker .components-input-control__input';
19
17
 
@@ -82,13 +80,11 @@ describe( 'Heading', () => {
82
80
  );
83
81
 
84
82
  await customTextColorButton.click();
85
- await page.click( CUSTOM_COLOR_DETAILS_BUTTON_SELECTOR );
86
83
  await page.waitForSelector( COLOR_INPUT_FIELD_SELECTOR );
87
84
  await page.click( COLOR_INPUT_FIELD_SELECTOR );
88
85
  await pressKeyWithModifier( 'primary', 'A' );
89
86
  await page.keyboard.type( '4b7f4d' );
90
- await page.waitForXPath( '//button//span[contains(text(), "4b7f4d")]' );
91
- await page.click( '.wp-block-post-title' );
87
+ await page.keyboard.press( 'Enter' );
92
88
  expect( await getEditedPostContent() ).toMatchInlineSnapshot( `
93
89
  "<!-- wp:heading {\\"level\\":3,\\"style\\":{\\"color\\":{\\"text\\":\\"#4b7f4d\\"}}} -->
94
90
  <h3 class=\\"has-text-color\\" style=\\"color:#4b7f4d\\">Heading</h3>
@@ -807,6 +807,58 @@ describe( 'Navigation', () => {
807
807
  );
808
808
  } );
809
809
 
810
+ it( 'correctly decodes special characters in the created Page title for display', async () => {
811
+ await createNewPost();
812
+ await insertBlock( 'Navigation' );
813
+ const startEmptyButton = await page.waitForXPath( START_EMPTY_XPATH );
814
+ await startEmptyButton.click();
815
+ const appender = await page.waitForSelector(
816
+ '.wp-block-navigation .block-list-appender'
817
+ );
818
+ await appender.click();
819
+
820
+ // Wait for URL input to be focused
821
+ // Insert name for the new page.
822
+ const pageTitle = 'This & That & Some < other > chars';
823
+ const input = await page.waitForSelector(
824
+ 'input.block-editor-url-input__input:focus'
825
+ );
826
+ await input.type( pageTitle );
827
+
828
+ // When creating a page, the URLControl makes a request to the
829
+ // url-details endpoint to fetch information about the page.
830
+ // Because the draft is inaccessible publicly, this request
831
+ // returns a 404 response. Wait for the response and expect
832
+ // the error to have occurred.
833
+ const createPageButton = await page.waitForSelector(
834
+ '.block-editor-link-control__search-create'
835
+ );
836
+ const responsePromise = page.waitForResponse(
837
+ ( response ) =>
838
+ response.url().includes( 'url-details' ) &&
839
+ response.status() === 404
840
+ );
841
+ const createPagePromise = createPageButton.click();
842
+ await Promise.all( [ responsePromise, createPagePromise ] );
843
+
844
+ await waitForBlock( 'Navigation' );
845
+
846
+ const innerLinkBlock = await waitForBlock( 'Custom Link' );
847
+
848
+ const linkText = await innerLinkBlock.$eval(
849
+ '[aria-label="Navigation link text"]',
850
+ ( element ) => {
851
+ return element.innerText;
852
+ }
853
+ );
854
+
855
+ expect( linkText ).toContain( pageTitle );
856
+
857
+ expect( console ).toHaveErroredWith(
858
+ 'Failed to load resource: the server responded with a status of 404 (Not Found)'
859
+ );
860
+ } );
861
+
810
862
  it( 'renders buttons for the submenu opener elements when the block is set to open on click instead of hover', async () => {
811
863
  await createClassicMenu( { name: 'Test Menu 2' }, menuItemsFixture );
812
864
  await createNewPost();
@@ -1294,11 +1346,9 @@ describe( 'Navigation', () => {
1294
1346
  `//*[contains(@class, 'components-snackbar__content')][ text()="You do not have permission to edit this Menu. Any changes made will not be saved." ]`
1295
1347
  );
1296
1348
 
1297
- // Expect a console 403 for request to Navigation Areas for lower permission users.
1298
- // This is because reading requires the `edit_theme_options` capability
1299
- // which the Contributor level user does not have.
1300
- // See: https://github.com/WordPress/gutenberg/blob/4cedaf0c4abb0aeac4bfd4289d63e9889efe9733/lib/class-wp-rest-block-navigation-areas-controller.php#L81-L91.
1301
- // Todo: removed once Nav Areas are removed from the Gutenberg Plugin.
1349
+ // Expect a console 403 for requests to:
1350
+ // * /wp/v2/settings?_locale=user
1351
+ // * /wp/v2/templates?context=edit&post_type=post&per_page=100&_locale=user
1302
1352
  expect( console ).toHaveErrored();
1303
1353
  } );
1304
1354
 
@@ -1317,11 +1367,9 @@ describe( 'Navigation', () => {
1317
1367
  `//*[contains(@class, 'components-snackbar__content')][ text()="${ noticeText }" ]`
1318
1368
  );
1319
1369
 
1320
- // Expect a console 403 for request to Navigation Areas for lower permission users.
1321
- // This is because reading requires the `edit_theme_options` capability
1322
- // which the Contributor level user does not have.
1323
- // See: https://github.com/WordPress/gutenberg/blob/4cedaf0c4abb0aeac4bfd4289d63e9889efe9733/lib/class-wp-rest-block-navigation-areas-controller.php#L81-L91.
1324
- // Todo: removed once Nav Areas are removed from the Gutenberg Plugin.
1370
+ // Expect a console 403 for requests to:
1371
+ // * /wp/v2/settings?_locale=user
1372
+ // * /wp/v2/templates?context=edit&post_type=post&per_page=100&_locale=user
1325
1373
  expect( console ).toHaveErrored();
1326
1374
  } );
1327
1375
  } );
@@ -32,6 +32,7 @@ describe( 'iframed inline styles', () => {
32
32
  await deactivatePlugin( 'gutenberg-test-iframed-inline-styles' );
33
33
  } );
34
34
 
35
+ // Skip flaky test. See https://github.com/WordPress/gutenberg/issues/35172
35
36
  it.skip( 'should load inline styles in iframe', async () => {
36
37
  await insertBlock( 'Iframed Inline Styles' );
37
38
 
@@ -108,7 +108,7 @@ exports[`Inserting blocks inserts a block in proper place after having clicked \
108
108
  exports[`Inserting blocks inserts blocks at root level when using the root appender while selection is in an inner block 1`] = `
109
109
  "<!-- wp:buttons -->
110
110
  <div class=\\"wp-block-buttons\\"><!-- wp:button -->
111
- <div class=\\"wp-block-button\\"><a class=\\"wp-block-button__link\\">1.1</a></div>
111
+ <div class=\\"wp-block-button\\"><a class=\\"wp-block-button__link wp-element-button\\">1.1</a></div>
112
112
  <!-- /wp:button --></div>
113
113
  <!-- /wp:buttons -->
114
114
 
@@ -15,12 +15,24 @@ async function getSelectedOptionLabel( selector ) {
15
15
  }
16
16
 
17
17
  async function getDatePickerValues() {
18
- const year = await getInputValue( '[aria-label="Year"]' );
19
- const month = await getInputValue( '[aria-label="Month"]' );
20
- const monthLabel = await getSelectedOptionLabel( '[aria-label="Month"]' );
21
- const day = await getInputValue( '[aria-label="Day"]' );
22
- const hours = await getInputValue( '[aria-label="Hours"]' );
23
- const minutes = await getInputValue( '[aria-label="Minutes"]' );
18
+ const year = await getInputValue(
19
+ '.components-datetime__time-field-year input'
20
+ );
21
+ const month = await getInputValue(
22
+ '.components-datetime__time-field-month select'
23
+ );
24
+ const monthLabel = await getSelectedOptionLabel(
25
+ '.components-datetime__time-field-month select'
26
+ );
27
+ const day = await getInputValue(
28
+ '.components-datetime__time-field-day input'
29
+ );
30
+ const hours = await getInputValue(
31
+ '.components-datetime__time-field-hours-input input'
32
+ );
33
+ const minutes = await getInputValue(
34
+ '.components-datetime__time-field-minutes-input input'
35
+ );
24
36
  const amOrPm = await page.$eval(
25
37
  '.components-datetime__time-field-am-pm .is-primary',
26
38
  ( element ) => element.innerText.toLowerCase()
@@ -126,7 +138,7 @@ describe.each( [ [ 'UTC-10' ], [ 'UTC' ], [ 'UTC+10' ] ] )(
126
138
  await page.click( '.edit-post-post-schedule__toggle' );
127
139
 
128
140
  // Clear the date.
129
- await page.click( '.components-datetime__date-reset-button' );
141
+ await page.click( '.block-editor-publish-date-time-picker__reset' );
130
142
 
131
143
  const publishingDate = await getPublishingDate();
132
144
 
@@ -92,7 +92,7 @@ describe( 'Post visibility', () => {
92
92
  // Set a publish date for the next month.
93
93
  await page.click( '.edit-post-post-schedule__toggle' );
94
94
  await page.click(
95
- 'div[aria-label="Move forward to switch to the next month."]'
95
+ '*[aria-label="Move forward to switch to the next month."]'
96
96
  );
97
97
  await (
98
98
  await page.$x(
@@ -58,11 +58,11 @@ describe( 'Scheduling', () => {
58
58
 
59
59
  await page.click( '.edit-post-post-schedule__toggle' );
60
60
  await page.click(
61
- 'div[aria-label="Move backward to switch to the previous month."]'
61
+ '*[aria-label="Move backward to switch to the previous month."]'
62
62
  );
63
63
  expect( await isDateTimeComponentFocused() ).toBe( true );
64
64
  await page.click(
65
- 'div[aria-label="Move forward to switch to the next month."]'
65
+ '*[aria-label="Move forward to switch to the next month."]'
66
66
  );
67
67
  expect( await isDateTimeComponentFocused() ).toBe( true );
68
68
  } );
@@ -63,7 +63,7 @@ async function scheduleTestPost( postType, viewport ) {
63
63
  // Set a publish date for the next month.
64
64
  await page.click( '.edit-post-post-schedule__toggle' );
65
65
  await page.click(
66
- 'div[aria-label="Move forward to switch to the next month."]'
66
+ '*[aria-label="Move forward to switch to the next month."]'
67
67
  );
68
68
 
69
69
  await (
@@ -734,4 +734,23 @@ describe( 'Writing Flow', () => {
734
734
  );
735
735
  expect( selectedParagraph ).toBeDefined();
736
736
  } );
737
+ it( 'should prevent browser default formatting on multi selection', async () => {
738
+ await page.keyboard.press( 'Enter' );
739
+ await page.keyboard.type( 'first' );
740
+ await page.keyboard.press( 'Enter' );
741
+ await page.keyboard.type( 'second' );
742
+
743
+ // Multi select both paragraphs.
744
+ await pressKeyTimes( 'ArrowLeft', 2 );
745
+ await page.keyboard.down( 'Shift' );
746
+ await pressKeyTimes( 'ArrowLeft', 2 );
747
+ await page.keyboard.press( 'ArrowUp' );
748
+ await page.keyboard.up( 'Shift' );
749
+ await pressKeyWithModifier( 'primary', 'b' );
750
+ const paragraphs = await page.$$eval(
751
+ '[data-type="core/paragraph"]',
752
+ ( nodes ) => Array.from( nodes ).map( ( node ) => node.innerHTML )
753
+ );
754
+ expect( paragraphs ).toEqual( [ 'first', 'second' ] );
755
+ } );
737
756
  } );
@@ -1,14 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`Code can be created by three backticks and enter 1`] = `
4
- "<!-- wp:code -->
5
- <pre class=\\"wp-block-code\\"><code>&lt;?php</code></pre>
6
- <!-- /wp:code -->"
7
- `;
8
-
9
- exports[`Code should paste plain text 1`] = `
10
- "<!-- wp:code -->
11
- <pre class=\\"wp-block-code\\"><code>&lt;img />
12
- &lt;br></code></pre>
13
- <!-- /wp:code -->"
14
- `;
@@ -1,8 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`HTML block can be created by typing "/html" 1`] = `
4
- "<!-- wp:html -->
5
- <p>Pythagorean theorem:
6
- <var>a</var><sup>2</sup> + <var>b</var><sup>2</sup> = <var>c</var><sup>2</sup> </p>
7
- <!-- /wp:html -->"
8
- `;
@@ -1,24 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`Preformatted should preserve character newlines 1`] = `
4
- "<!-- wp:html -->
5
- <pre>1
6
- 2</pre>
7
- <!-- /wp:html -->"
8
- `;
9
-
10
- exports[`Preformatted should preserve character newlines 2`] = `
11
- "<!-- wp:preformatted -->
12
- <pre class=\\"wp-block-preformatted\\">0
13
- 1
14
- 2</pre>
15
- <!-- /wp:preformatted -->"
16
- `;
17
-
18
- exports[`Preformatted should preserve white space when merging 1`] = `
19
- "<!-- wp:preformatted -->
20
- <pre class=\\"wp-block-preformatted\\">1
21
- 2
22
- 3</pre>
23
- <!-- /wp:preformatted -->"
24
- `;
@@ -1,7 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`Separator can be created by three dashes and enter 1`] = `
4
- "<!-- wp:separator -->
5
- <hr class=\\"wp-block-separator has-alpha-channel-opacity\\"/>
6
- <!-- /wp:separator -->"
7
- `;
@@ -1,48 +0,0 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import {
5
- insertBlock,
6
- clickBlockAppender,
7
- getEditedPostContent,
8
- createNewPost,
9
- setClipboardData,
10
- pressKeyWithModifier,
11
- } from '@wordpress/e2e-test-utils';
12
-
13
- describe( 'Code', () => {
14
- beforeEach( async () => {
15
- await createNewPost();
16
- } );
17
-
18
- it( 'can be created by three backticks and enter', async () => {
19
- await clickBlockAppender();
20
- await page.keyboard.type( '```' );
21
- await page.keyboard.press( 'Enter' );
22
- await page.keyboard.type( '<?php' );
23
-
24
- expect( await getEditedPostContent() ).toMatchSnapshot();
25
- } );
26
-
27
- it( 'should delete block when backspace in an empty code', async () => {
28
- await insertBlock( 'Code' );
29
- await page.keyboard.type( 'a' );
30
-
31
- await page.keyboard.press( 'Backspace' );
32
- await page.keyboard.press( 'Backspace' );
33
-
34
- // Expect code block to be deleted.
35
- expect( await getEditedPostContent() ).toBe( '' );
36
- } );
37
-
38
- it( 'should paste plain text', async () => {
39
- await insertBlock( 'Code' );
40
-
41
- // Test to see if HTML and white space is kept.
42
- await setClipboardData( { plainText: '<img />\n\t<br>' } );
43
-
44
- await pressKeyWithModifier( 'primary', 'v' );
45
-
46
- expect( await getEditedPostContent() ).toMatchSnapshot();
47
- } );
48
- } );
@@ -1,31 +0,0 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import {
5
- clickBlockAppender,
6
- getEditedPostContent,
7
- createNewPost,
8
- } from '@wordpress/e2e-test-utils';
9
-
10
- describe( 'HTML block', () => {
11
- beforeEach( async () => {
12
- await createNewPost();
13
- } );
14
-
15
- it( 'can be created by typing "/html"', async () => {
16
- // Create a Custom HTML block with the slash shortcut.
17
- await clickBlockAppender();
18
- await page.keyboard.type( '/html' );
19
- await page.waitForXPath(
20
- `//*[contains(@class, "components-autocomplete__result") and contains(@class, "is-selected") and contains(text(), 'Custom HTML')]`
21
- );
22
- await page.keyboard.press( 'Enter' );
23
- await page.keyboard.type( '<p>Pythagorean theorem: ' );
24
- await page.keyboard.press( 'Enter' );
25
- await page.keyboard.type(
26
- '<var>a</var><sup>2</sup> + <var>b</var><sup>2</sup> = <var>c</var><sup>2</sup> </p>'
27
- );
28
-
29
- expect( await getEditedPostContent() ).toMatchSnapshot();
30
- } );
31
- } );
@@ -1,62 +0,0 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import {
5
- clickBlockToolbarButton,
6
- clickMenuItem,
7
- getEditedPostContent,
8
- createNewPost,
9
- insertBlock,
10
- clickBlockAppender,
11
- } from '@wordpress/e2e-test-utils';
12
-
13
- describe( 'Preformatted', () => {
14
- beforeEach( async () => {
15
- await createNewPost();
16
- } );
17
-
18
- it( 'should preserve character newlines', async () => {
19
- await insertBlock( 'Custom HTML' );
20
- await page.keyboard.type( '<pre>1' );
21
- await page.keyboard.press( 'Enter' );
22
- await page.keyboard.type( '2</pre>' );
23
-
24
- expect( await getEditedPostContent() ).toMatchSnapshot();
25
-
26
- await clickBlockToolbarButton( 'Options' );
27
- await clickMenuItem( 'Convert to Blocks' );
28
- // Once it's edited, it should be saved as BR tags.
29
- await page.keyboard.type( '0' );
30
- await page.keyboard.press( 'Enter' );
31
- await clickBlockToolbarButton( 'Options' );
32
- await clickMenuItem( 'Edit as HTML' );
33
-
34
- expect( await getEditedPostContent() ).toMatchSnapshot();
35
- } );
36
-
37
- it( 'should preserve white space when merging', async () => {
38
- await insertBlock( 'Preformatted' );
39
- await page.keyboard.type( '1' );
40
- await page.keyboard.press( 'Enter' );
41
- await page.keyboard.type( '2' );
42
- await page.keyboard.press( 'Enter' );
43
- await clickBlockAppender();
44
- await page.keyboard.type( '3' );
45
- await page.keyboard.press( 'ArrowLeft' );
46
- await page.keyboard.press( 'Backspace' );
47
-
48
- expect( await getEditedPostContent() ).toMatchSnapshot();
49
- } );
50
-
51
- it( 'should delete block when backspace in an empty preformatted', async () => {
52
- await insertBlock( 'Preformatted' );
53
-
54
- await page.keyboard.type( 'a' );
55
-
56
- await page.keyboard.press( 'Backspace' );
57
- await page.keyboard.press( 'Backspace' );
58
-
59
- // Expect preformatted block to be deleted.
60
- expect( await getEditedPostContent() ).toBe( '' );
61
- } );
62
- } );
@@ -1,22 +0,0 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import {
5
- clickBlockAppender,
6
- getEditedPostContent,
7
- createNewPost,
8
- } from '@wordpress/e2e-test-utils';
9
-
10
- describe( 'Separator', () => {
11
- beforeEach( async () => {
12
- await createNewPost();
13
- } );
14
-
15
- it( 'can be created by three dashes and enter', async () => {
16
- await clickBlockAppender();
17
- await page.keyboard.type( '---' );
18
- await page.keyboard.press( 'Enter' );
19
-
20
- expect( await getEditedPostContent() ).toMatchSnapshot();
21
- } );
22
- } );
@@ -1,346 +0,0 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import {
5
- insertBlock,
6
- deleteAllTemplates,
7
- activateTheme,
8
- getAllBlocks,
9
- selectBlockByClientId,
10
- clickBlockToolbarButton,
11
- canvas,
12
- visitSiteEditor,
13
- } from '@wordpress/e2e-test-utils';
14
-
15
- const templatePartNameInput =
16
- '.edit-site-create-template-part-modal .components-text-control__input';
17
-
18
- describe( 'Template Part', () => {
19
- beforeAll( async () => {
20
- await activateTheme( 'emptytheme' );
21
- await deleteAllTemplates( 'wp_template' );
22
- await deleteAllTemplates( 'wp_template_part' );
23
- } );
24
- afterEach( async () => {
25
- await deleteAllTemplates( 'wp_template' );
26
- await deleteAllTemplates( 'wp_template_part' );
27
- } );
28
- afterAll( async () => {
29
- await activateTheme( 'twentytwentyone' );
30
- } );
31
-
32
- describe( 'Template part block', () => {
33
- beforeEach( async () => {
34
- await visitSiteEditor();
35
- } );
36
-
37
- async function navigateToHeader() {
38
- // Switch to editing the header template part.
39
- await visitSiteEditor( {
40
- postId: 'emptytheme//header',
41
- postType: 'wp_template_part',
42
- } );
43
- }
44
-
45
- async function updateHeader( content ) {
46
- await navigateToHeader();
47
-
48
- // Edit it.
49
- await insertBlock( 'Paragraph' );
50
- await page.keyboard.type( content );
51
-
52
- // Save it.
53
- await page.click( '.edit-site-save-button__button' );
54
- await page.click( '.editor-entities-saved-states__save-button' );
55
- await page.waitForSelector(
56
- '.edit-site-save-button__button:not(.is-busy)'
57
- );
58
-
59
- // Switch back to the Index template.
60
- await visitSiteEditor( {
61
- postId: 'emptytheme//index',
62
- postType: 'wp_template',
63
- } );
64
- }
65
-
66
- async function triggerEllipsisMenuItem( textPrompt ) {
67
- await clickBlockToolbarButton( 'Options' );
68
- const button = await page.waitForXPath(
69
- `//span[contains(text(), "${ textPrompt }")]`
70
- );
71
- await button.click();
72
- }
73
-
74
- async function createParagraphAndGetClientId( content ) {
75
- await insertBlock( 'Paragraph' );
76
- await page.keyboard.type( content );
77
- const allBlocks = await getAllBlocks();
78
- const paragraphBlock = allBlocks.find(
79
- ( block ) =>
80
- block.name === 'core/paragraph' &&
81
- block.attributes.content === content
82
- );
83
- return paragraphBlock.clientId;
84
- }
85
-
86
- async function assertParagraphInTemplatePart( content ) {
87
- const paragraphInTemplatePart = await canvas().waitForXPath(
88
- `//*[@data-type="core/template-part"][//p[text()="${ content }"]]`
89
- );
90
- expect( paragraphInTemplatePart ).not.toBeNull();
91
- }
92
-
93
- async function awaitHeaderLoad() {
94
- await canvas().waitForSelector(
95
- 'header.wp-block-template-part.block-editor-block-list__layout'
96
- );
97
- }
98
-
99
- it( 'Should load customizations when in a template even if only the slug and theme attributes are set.', async () => {
100
- await updateHeader( 'Header Template Part 123' );
101
-
102
- // Verify that the header template part is updated.
103
- await assertParagraphInTemplatePart( 'Header Template Part 123' );
104
- } );
105
-
106
- it( 'Should detach blocks from template part', async () => {
107
- await updateHeader( 'Header Template Part 456' );
108
-
109
- const initialTemplateParts = await canvas().$$(
110
- '.wp-block-template-part'
111
- );
112
-
113
- // Select the header template part block.
114
- const allBlocks = await getAllBlocks();
115
- const headerBlock = allBlocks.find(
116
- ( block ) => block.name === 'core/template-part'
117
- );
118
- await selectBlockByClientId( headerBlock.clientId );
119
-
120
- // Detach blocks from template part using ellipsis menu.
121
- await triggerEllipsisMenuItem( 'Detach blocks from template part' );
122
-
123
- // Verify there is one less template part on the page.
124
- const finalTemplateParts = await canvas().$$(
125
- '.wp-block-template-part'
126
- );
127
- expect(
128
- initialTemplateParts.length - finalTemplateParts.length
129
- ).toBe( 1 );
130
-
131
- // Verify content of the template part is still present.
132
- const [ expectedContent ] = await canvas().$x(
133
- '//p[contains(text(), "Header Template Part 456")]'
134
- );
135
- expect( expectedContent ).not.toBeUndefined();
136
- } );
137
-
138
- it( 'Should load navigate-to-links properly', async () => {
139
- await navigateToHeader();
140
- await insertBlock( 'Paragraph' );
141
- await page.keyboard.type( 'Header Template Part 789' );
142
-
143
- // Select the paragraph block.
144
- const text = await canvas().waitForXPath(
145
- '//p[contains(text(), "Header Template Part 789")]'
146
- );
147
-
148
- // Highlight all the text in the paragraph block.
149
- await text.click( { clickCount: 3 } );
150
-
151
- // Click the convert to link toolbar button.
152
- await page.waitForSelector( 'button[aria-label="Link"]' );
153
- await page.click( 'button[aria-label="Link"]' );
154
-
155
- // Enter url for link.
156
- await page.keyboard.type( 'https://google.com' );
157
- await page.keyboard.press( 'Enter' );
158
-
159
- // Verify that there is no error.
160
- await canvas().click( 'p[data-type="core/paragraph"] a' );
161
- const expectedContent = await canvas().$x(
162
- '//p[contains(text(), "Header Template Part 789")]'
163
- );
164
-
165
- expect( expectedContent ).not.toBeUndefined();
166
- } );
167
-
168
- it( 'Should convert selected block to template part', async () => {
169
- await awaitHeaderLoad();
170
- const initialTemplateParts = await canvas().$$(
171
- '.wp-block-template-part'
172
- );
173
-
174
- // Add some block and select it.
175
- const clientId = await createParagraphAndGetClientId(
176
- 'Some block...'
177
- );
178
- await selectBlockByClientId( clientId );
179
-
180
- // Convert block to a template part.
181
- await triggerEllipsisMenuItem( 'Make template part' );
182
- const nameInput = await page.waitForSelector(
183
- templatePartNameInput
184
- );
185
- await nameInput.click();
186
- await page.keyboard.type( 'My template part' );
187
- await page.keyboard.press( 'Enter' );
188
-
189
- // Wait for creation to finish.
190
- await page.waitForXPath(
191
- '//*[contains(@class, "components-snackbar")]/*[text()="Template part created."]'
192
- );
193
-
194
- // Verify new template part is created with expected content.
195
- await assertParagraphInTemplatePart( 'Some block...' );
196
-
197
- // Verify there is 1 more template part on the page than previously.
198
- const finalTemplateParts = await canvas().$$(
199
- '.wp-block-template-part'
200
- );
201
- expect(
202
- finalTemplateParts.length - initialTemplateParts.length
203
- ).toBe( 1 );
204
- } );
205
-
206
- it( 'Should convert multiple selected blocks to template part', async () => {
207
- await awaitHeaderLoad();
208
- const initialTemplateParts = await canvas().$$(
209
- '.wp-block-template-part'
210
- );
211
-
212
- // Add two blocks and select them.
213
- const block1Id = await createParagraphAndGetClientId(
214
- 'Some block #1'
215
- );
216
- const block2Id = await createParagraphAndGetClientId(
217
- 'Some block #2'
218
- );
219
- await page.evaluate(
220
- ( id1, id2 ) => {
221
- wp.data
222
- .dispatch( 'core/block-editor' )
223
- .multiSelect( id1, id2 );
224
- },
225
- block1Id,
226
- block2Id
227
- );
228
-
229
- // Convert block to a template part.
230
- await triggerEllipsisMenuItem( 'Make template part' );
231
- const nameInput = await page.waitForSelector(
232
- templatePartNameInput
233
- );
234
- await nameInput.click();
235
- await page.keyboard.type( 'My multi template part' );
236
- await page.keyboard.press( 'Enter' );
237
-
238
- // Wait for creation to finish.
239
- await page.waitForXPath(
240
- '//*[contains(@class, "components-snackbar")]/*[text()="Template part created."]'
241
- );
242
-
243
- // Verify new template part is created with expected content.
244
- await assertParagraphInTemplatePart( 'Some block #1' );
245
- await assertParagraphInTemplatePart( 'Some block #2' );
246
-
247
- // Verify there is 1 more template part on the page than previously.
248
- const finalTemplateParts = await canvas().$$(
249
- '.wp-block-template-part'
250
- );
251
- expect(
252
- finalTemplateParts.length - initialTemplateParts.length
253
- ).toBe( 1 );
254
- } );
255
-
256
- describe( 'Template part placeholder', () => {
257
- // Test constants for template part.
258
- const testContent = 'some words...';
259
-
260
- // Selectors.
261
- const entitiesSaveSelector =
262
- '.editor-entities-saved-states__save-button';
263
- const savePostSelector = '.edit-site-save-button__button';
264
- const templatePartSelector = '*[data-type="core/template-part"]';
265
- const activatedTemplatePartSelector = `${ templatePartSelector }.block-editor-block-list__layout`;
266
- const startBlockButtonSelector =
267
- '//button[contains(text(), "Start blank")]';
268
- const chooseExistingButtonSelector =
269
- '//button[contains(text(), "Choose")]';
270
- const confirmTitleButtonSelector =
271
- '.wp-block-template-part__placeholder-create-new__title-form .components-button.is-primary';
272
-
273
- it( 'Should insert new template part on creation', async () => {
274
- let siteEditorCanvas = canvas();
275
- await awaitHeaderLoad();
276
-
277
- // Create new template part.
278
- await insertBlock( 'Template Part' );
279
- const startBlankButton = await siteEditorCanvas.waitForXPath(
280
- startBlockButtonSelector
281
- );
282
- await startBlankButton.click();
283
- const confirmTitleButton = await page.waitForSelector(
284
- confirmTitleButtonSelector
285
- );
286
- await page.keyboard.press( 'Tab' );
287
- await page.keyboard.press( 'Tab' );
288
- await page.keyboard.type( 'Create New' );
289
- await confirmTitleButton.click();
290
-
291
- const newTemplatePart = await siteEditorCanvas.waitForSelector(
292
- activatedTemplatePartSelector
293
- );
294
- expect( newTemplatePart ).toBeTruthy();
295
-
296
- // Finish creating template part, insert some text, and save.
297
- await siteEditorCanvas.waitForSelector(
298
- '.block-editor-button-block-appender'
299
- );
300
- await siteEditorCanvas.click(
301
- '.block-editor-button-block-appender'
302
- );
303
- await page.waitForSelector(
304
- '.editor-block-list-item-paragraph'
305
- );
306
- await page.click( '.editor-block-list-item-paragraph' );
307
- await page.keyboard.type( testContent );
308
- await page.click( savePostSelector );
309
- await page.click( entitiesSaveSelector );
310
-
311
- // Reload the page so as the new template part is available in the existing template parts.
312
- await visitSiteEditor();
313
- siteEditorCanvas = canvas();
314
- await awaitHeaderLoad();
315
- // Try to insert the template part we created.
316
- await insertBlock( 'Template Part' );
317
- const chooseExistingButton = await siteEditorCanvas.waitForXPath(
318
- chooseExistingButtonSelector
319
- );
320
- await chooseExistingButton.click();
321
- const preview = await page.waitForSelector(
322
- '.block-editor-block-patterns-list__item'
323
- );
324
- await preview.click();
325
-
326
- // Wait for the template parts to load properly.
327
- await siteEditorCanvas.waitForSelector(
328
- '[data-type="core/template-part"] > p:first-child'
329
- );
330
-
331
- // We now have the same template part two times in the page, so check accordingly.
332
- const paragraphs = await siteEditorCanvas.$$eval(
333
- '[data-type="core/template-part"] > p:first-child',
334
- ( options ) =>
335
- options.map( ( option ) => option.textContent )
336
- );
337
- expect( paragraphs ).toHaveLength( 2 );
338
- expect(
339
- paragraphs.every(
340
- ( paragraph ) => paragraph === testContent
341
- )
342
- ).toBeTruthy();
343
- } );
344
- } );
345
- } );
346
- } );
@@ -1,209 +0,0 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import {
5
- insertBlock,
6
- activateTheme,
7
- deleteAllTemplates,
8
- visitSiteEditor,
9
- getCurrentSiteEditorContent,
10
- } from '@wordpress/e2e-test-utils';
11
-
12
- const assertSaveButtonIsDisabled = async () =>
13
- page.waitForSelector(
14
- '.edit-site-save-button__button[aria-disabled="true"]'
15
- );
16
-
17
- const assertSaveButtonIsEnabled = async () =>
18
- page.waitForSelector(
19
- '.edit-site-save-button__button[aria-disabled="false"]'
20
- );
21
-
22
- const clickButtonInNotice = async () => {
23
- const selector = '.components-snackbar button';
24
- await page.waitForSelector( selector );
25
- await page.click( selector );
26
- };
27
-
28
- const clickUndoInHeaderToolbar = async () =>
29
- page.click( '.edit-site-header__toolbar button[aria-label="Undo"]' );
30
-
31
- const clickRedoInHeaderToolbar = async () => {
32
- await page.waitForSelector(
33
- '.edit-site-header__toolbar button[aria-label="Redo"][aria-disabled="false"]'
34
- );
35
- return page.click( '.edit-site-header__toolbar button[aria-label="Redo"]' );
36
- };
37
-
38
- const undoRevertInHeaderToolbar = async () => {
39
- await clickUndoInHeaderToolbar();
40
- await assertSaveButtonIsEnabled();
41
- };
42
-
43
- const undoRevertInNotice = async () => {
44
- await clickButtonInNotice();
45
- await assertSaveButtonIsEnabled();
46
- };
47
-
48
- const addDummyText = async () => {
49
- await insertBlock( 'Paragraph' );
50
- await page.keyboard.type( 'Test' );
51
- };
52
-
53
- const save = async () => {
54
- await page.click( '.edit-site-save-button__button' );
55
- await page.click( '.editor-entities-saved-states__save-button' );
56
- await page.waitForSelector(
57
- '.edit-site-save-button__button:not(.is-busy)'
58
- );
59
- };
60
-
61
- const revertTemplate = async () => {
62
- await page.click( '.edit-site-document-actions__get-info' );
63
- await page.click( '.edit-site-template-details__revert-button' );
64
- await page.waitForXPath(
65
- '//*[contains(@class, "components-snackbar") and contains(text(), "Template reverted")]'
66
- );
67
- await assertSaveButtonIsEnabled();
68
- };
69
-
70
- describe( 'Template Revert', () => {
71
- beforeAll( async () => {
72
- await activateTheme( 'emptytheme' );
73
- await deleteAllTemplates( 'wp_template' );
74
- await deleteAllTemplates( 'wp_template_part' );
75
- } );
76
- afterAll( async () => {
77
- await deleteAllTemplates( 'wp_template' );
78
- await deleteAllTemplates( 'wp_template_part' );
79
- await activateTheme( 'twentytwentyone' );
80
- } );
81
- beforeEach( async () => {
82
- await deleteAllTemplates( 'wp_template' );
83
- await visitSiteEditor();
84
- } );
85
-
86
- it( 'should delete the template after saving the reverted template', async () => {
87
- await addDummyText();
88
- await save();
89
- await revertTemplate();
90
- await save();
91
-
92
- await page.click( '.edit-site-document-actions__get-info' );
93
-
94
- // The revert button isn't visible anymore.
95
- expect(
96
- await page.$( '.edit-site-template-details__revert-button' )
97
- ).toBeNull();
98
- } );
99
-
100
- it( 'should show the original content after revert', async () => {
101
- const contentBefore = await getCurrentSiteEditorContent();
102
-
103
- await addDummyText();
104
- await save();
105
- await revertTemplate();
106
- await save();
107
-
108
- const contentAfter = await getCurrentSiteEditorContent();
109
- expect( contentBefore ).toBe( contentAfter );
110
- } );
111
-
112
- it( 'should show the original content after revert and page reload', async () => {
113
- const contentBefore = await getCurrentSiteEditorContent();
114
-
115
- await addDummyText();
116
- await save();
117
- await revertTemplate();
118
- await save();
119
- await visitSiteEditor();
120
-
121
- const contentAfter = await getCurrentSiteEditorContent();
122
- expect( contentBefore ).toBe( contentAfter );
123
- } );
124
-
125
- it( 'should show the edited content after revert and clicking undo in the header toolbar', async () => {
126
- await addDummyText();
127
- await save();
128
- const contentBefore = await getCurrentSiteEditorContent();
129
-
130
- await revertTemplate();
131
- await save();
132
- await undoRevertInHeaderToolbar();
133
-
134
- const contentAfter = await getCurrentSiteEditorContent();
135
- expect( contentBefore ).toBe( contentAfter );
136
- } );
137
-
138
- it( 'should show the edited content after revert and clicking undo in the notice', async () => {
139
- await addDummyText();
140
- await save();
141
- const contentBefore = await getCurrentSiteEditorContent();
142
-
143
- await revertTemplate();
144
- await save();
145
- await undoRevertInNotice();
146
-
147
- const contentAfter = await getCurrentSiteEditorContent();
148
- expect( contentBefore ).toBe( contentAfter );
149
- } );
150
-
151
- it( 'should show the original content after revert, clicking undo then redo in the header toolbar', async () => {
152
- const contentBefore = await getCurrentSiteEditorContent();
153
-
154
- await addDummyText();
155
- await save();
156
- await revertTemplate();
157
- await save();
158
- await undoRevertInHeaderToolbar();
159
- await clickRedoInHeaderToolbar();
160
-
161
- const contentAfter = await getCurrentSiteEditorContent();
162
- expect( contentBefore ).toBe( contentAfter );
163
- } );
164
-
165
- it( 'should show the original content after revert, clicking undo in the notice then undo in the header toolbar', async () => {
166
- const contentBefore = await getCurrentSiteEditorContent();
167
-
168
- await addDummyText();
169
- await save();
170
- await revertTemplate();
171
- await save();
172
- await undoRevertInNotice();
173
- await undoRevertInHeaderToolbar();
174
-
175
- const contentAfter = await getCurrentSiteEditorContent();
176
- expect( contentBefore ).toBe( contentAfter );
177
- } );
178
-
179
- it( 'should show the edited content after revert, clicking undo in the header toolbar, save and reload', async () => {
180
- await addDummyText();
181
- await save();
182
- const contentBefore = await getCurrentSiteEditorContent();
183
-
184
- await revertTemplate();
185
- await save();
186
- await clickUndoInHeaderToolbar();
187
- await save();
188
- await assertSaveButtonIsDisabled();
189
- await visitSiteEditor();
190
-
191
- const contentAfter = await getCurrentSiteEditorContent();
192
- expect( contentBefore ).toBe( contentAfter );
193
- } );
194
-
195
- it( 'should show the edited content after revert, clicking undo in the notice and reload', async () => {
196
- await addDummyText();
197
- await save();
198
- const contentBefore = await getCurrentSiteEditorContent();
199
-
200
- await revertTemplate();
201
- await save();
202
- await undoRevertInNotice();
203
- await save();
204
- await visitSiteEditor();
205
-
206
- const contentAfter = await getCurrentSiteEditorContent();
207
- expect( contentBefore ).toBe( contentAfter );
208
- } );
209
- } );