@wordpress/e2e-tests 3.0.2 → 3.0.6

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 (44) hide show
  1. package/README.md +31 -19
  2. package/config/is-gutenberg-plugin.js +6 -0
  3. package/jest.config.js +1 -1
  4. package/jest.performance.config.js +1 -1
  5. package/mu-plugins/enable-templates-ui.php +24 -0
  6. package/package.json +7 -7
  7. package/plugins/plugins-api/error-boundary.js +11 -0
  8. package/plugins/plugins-error-boundary.php +27 -0
  9. package/specs/editor/blocks/__snapshots__/image.test.js.snap +6 -6
  10. package/specs/editor/blocks/__snapshots__/navigation.test.js.snap +0 -2
  11. package/specs/editor/blocks/cover.test.js +7 -3
  12. package/specs/editor/blocks/gallery.test.js +6 -1
  13. package/specs/editor/blocks/heading.test.js +1 -11
  14. package/specs/editor/blocks/navigation.test.js +0 -50
  15. package/specs/editor/plugins/__snapshots__/plugins-api.test.js.snap +2 -2
  16. package/specs/editor/plugins/block-directory-add.test.js +15 -1
  17. package/specs/editor/plugins/block-variations.test.js +2 -2
  18. package/specs/editor/plugins/plugins-api.test.js +30 -0
  19. package/specs/editor/plugins/templates.test.js +1 -7
  20. package/specs/editor/various/__snapshots__/inserting-blocks.test.js.snap +1 -1
  21. package/specs/editor/various/__snapshots__/keep-styles-on-block-transforms.test.js.snap +35 -0
  22. package/specs/editor/various/fullscreen-mode.test.js +1 -1
  23. package/specs/editor/various/keep-styles-on-block-transforms.test.js +81 -0
  24. package/specs/editor/various/post-visibility.test.js +54 -0
  25. package/specs/editor/various/style-variation.test.js +9 -5
  26. package/specs/performance/site-editor.test.js +2 -3
  27. package/specs/site-editor/document-settings.test.js +8 -10
  28. package/specs/site-editor/multi-entity-editing.test.js +12 -14
  29. package/specs/site-editor/multi-entity-saving.test.js +3 -9
  30. package/specs/site-editor/settings-sidebar.test.js +3 -8
  31. package/specs/site-editor/site-editor-export.test.js +8 -9
  32. package/specs/site-editor/site-editor-inserter.test.js +6 -8
  33. package/specs/site-editor/style-variations.test.js +211 -0
  34. package/specs/site-editor/template-part.test.js +5 -10
  35. package/specs/site-editor/template-revert.test.js +18 -28
  36. package/themes/style-variations/block-templates/index.html +11 -0
  37. package/themes/style-variations/index.php +0 -0
  38. package/themes/style-variations/style.css +15 -0
  39. package/themes/style-variations/styles/pink.json +33 -0
  40. package/themes/style-variations/styles/yellow.json +12 -0
  41. package/themes/style-variations/theme.json +8 -0
  42. package/config/gutenberg-phase.js +0 -9
  43. package/specs/editor/various/__snapshots__/style-variation.test.js.snap +0 -7
  44. package/specs/site-editor/utils.js +0 -153
@@ -0,0 +1,81 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import {
5
+ clickBlockAppender,
6
+ createNewPost,
7
+ getEditedPostContent,
8
+ pressKeyWithModifier,
9
+ transformBlockTo,
10
+ } from '@wordpress/e2e-test-utils';
11
+
12
+ describe( 'Keep styles on block transforms', () => {
13
+ beforeEach( async () => {
14
+ await createNewPost();
15
+ } );
16
+
17
+ it( 'Should keep colors during a transform', async () => {
18
+ await clickBlockAppender();
19
+ await page.keyboard.type( '## Heading' );
20
+
21
+ const textColorButton = await page.waitForSelector(
22
+ '.block-editor-panel-color-gradient-settings__dropdown'
23
+ );
24
+ await textColorButton.click();
25
+
26
+ const colorButtonSelector = `//button[@aria-label='Color: Luminous vivid orange']`;
27
+ const [ colorButton ] = await page.$x( colorButtonSelector );
28
+ await colorButton.click();
29
+ await page.waitForXPath(
30
+ `${ colorButtonSelector }[@aria-pressed='true']`
31
+ );
32
+ await page.click( 'h2[data-type="core/heading"]' );
33
+ await transformBlockTo( 'Paragraph' );
34
+ expect( await getEditedPostContent() ).toMatchSnapshot();
35
+ } );
36
+
37
+ it( 'Should keep the font size during a transform from multiple blocks into a single one', async () => {
38
+ // Create a paragraph block with some content.
39
+ await clickBlockAppender();
40
+ await page.keyboard.type( 'Line 1 to be made large' );
41
+ await page.keyboard.press( 'Enter' );
42
+ await page.keyboard.type( 'Line 2 to be made large' );
43
+ await page.keyboard.press( 'Enter' );
44
+ await page.keyboard.type( 'Line 3 to be made large' );
45
+ await pressKeyWithModifier( 'shift', 'ArrowUp' );
46
+ await pressKeyWithModifier( 'shift', 'ArrowUp' );
47
+ await page.click(
48
+ '[role="radiogroup"][aria-label="Font size"] [aria-label="Large"]'
49
+ );
50
+ await transformBlockTo( 'List' );
51
+ expect( await getEditedPostContent() ).toMatchSnapshot();
52
+ } );
53
+
54
+ it( 'Should keep the font size during a transform from multiple blocks into multiple blocks', async () => {
55
+ // Create a paragraph block with some content.
56
+ await clickBlockAppender();
57
+ await page.keyboard.type( 'Line 1 to be made large' );
58
+ await page.keyboard.press( 'Enter' );
59
+ await page.keyboard.type( 'Line 2 to be made large' );
60
+ await page.keyboard.press( 'Enter' );
61
+ await page.keyboard.type( 'Line 3 to be made large' );
62
+ await pressKeyWithModifier( 'shift', 'ArrowUp' );
63
+ await pressKeyWithModifier( 'shift', 'ArrowUp' );
64
+ await page.click(
65
+ '[role="radiogroup"][aria-label="Font size"] [aria-label="Large"]'
66
+ );
67
+ await transformBlockTo( 'Heading' );
68
+ expect( await getEditedPostContent() ).toMatchSnapshot();
69
+ } );
70
+
71
+ it( 'Should not include styles in the group block when grouping a block', async () => {
72
+ // Create a paragraph block with some content.
73
+ await clickBlockAppender();
74
+ await page.keyboard.type( 'Line 1 to be made large' );
75
+ await page.click(
76
+ '[role="radiogroup"][aria-label="Font size"] [aria-label="Large"]'
77
+ );
78
+ await transformBlockTo( 'Group' );
79
+ expect( await getEditedPostContent() ).toMatchSnapshot();
80
+ } );
81
+ } );
@@ -26,6 +26,15 @@ describe( 'Post visibility', () => {
26
26
  );
27
27
  await privateLabel.click();
28
28
 
29
+ await page.waitForXPath(
30
+ '//*[text()="Would you like to privately publish this post now?"]'
31
+ );
32
+
33
+ const [ confirmButton ] = await page.$x(
34
+ '//*[@role="dialog"]//button[text()="OK"]'
35
+ );
36
+ await confirmButton.click();
37
+
29
38
  const currentStatus = await page.evaluate( () => {
30
39
  return wp.data
31
40
  .select( 'core/editor' )
@@ -34,6 +43,42 @@ describe( 'Post visibility', () => {
34
43
 
35
44
  expect( currentStatus ).toBe( 'private' );
36
45
  } );
46
+
47
+ it( `can be canceled when the viewport is ${ viewport }`, async () => {
48
+ await setBrowserViewport( viewport );
49
+
50
+ await createNewPost();
51
+
52
+ await openDocumentSettingsSidebar();
53
+
54
+ const initialStatus = await page.evaluate( () => {
55
+ return wp.data
56
+ .select( 'core/editor' )
57
+ .getEditedPostAttribute( 'status' );
58
+ } );
59
+
60
+ await page.click( '.edit-post-post-visibility__toggle' );
61
+
62
+ const [ privateLabel ] = await page.$x(
63
+ '//label[text()="Private"]'
64
+ );
65
+ await privateLabel.click();
66
+ await page.waitForXPath(
67
+ '//*[text()="Would you like to privately publish this post now?"]'
68
+ );
69
+ const cancelButton = await page.waitForXPath(
70
+ '//*[@role="dialog"][not(@id="wp-link-wrap")]//button[text()="Cancel"]'
71
+ );
72
+ await cancelButton.click();
73
+
74
+ const currentStatus = await page.evaluate( () => {
75
+ return wp.data
76
+ .select( 'core/editor' )
77
+ .getEditedPostAttribute( 'status' );
78
+ } );
79
+
80
+ expect( currentStatus ).toBe( initialStatus );
81
+ } );
37
82
  } );
38
83
 
39
84
  it( 'visibility remains private even if the publish date is in the future', async () => {
@@ -60,6 +105,15 @@ describe( 'Post visibility', () => {
60
105
  const [ privateLabel ] = await page.$x( '//label[text()="Private"]' );
61
106
  await privateLabel.click();
62
107
 
108
+ await page.waitForXPath(
109
+ '//*[text()="Would you like to privately publish this post now?"]'
110
+ );
111
+
112
+ const [ confirmButton ] = await page.$x(
113
+ '//*[@role="dialog"]//button[text()="OK"]'
114
+ );
115
+ await confirmButton.click();
116
+
63
117
  // Enter a title for this post.
64
118
  await page.type( '.editor-post-title__input', ' Changed' );
65
119
 
@@ -13,20 +13,24 @@ describe( 'adding blocks', () => {
13
13
  await createNewPost();
14
14
  } );
15
15
 
16
- it( 'Should switch to the large style of the quote block', async () => {
16
+ it( 'Should switch to the plain style of the quote block', async () => {
17
17
  // Inserting a quote block
18
18
  await insertBlock( 'Quote' );
19
19
  await page.keyboard.type( 'Quote content' );
20
20
 
21
21
  await clickBlockToolbarButton( 'Quote' );
22
22
 
23
- const largeStyleButton = await page.waitForXPath(
24
- '//*[@role="menuitem"][contains(., "Large")]'
23
+ const plainStyleButton = await page.waitForXPath(
24
+ '//*[@role="menuitem"][contains(., "Plain")]'
25
25
  );
26
- await largeStyleButton.click();
26
+ await plainStyleButton.click();
27
27
 
28
28
  // Check the content
29
29
  const content = await getEditedPostContent();
30
- expect( content ).toMatchSnapshot();
30
+ expect( content ).toMatchInlineSnapshot( `
31
+ "<!-- wp:quote {\\"className\\":\\"is-style-plain\\"} -->
32
+ <blockquote class=\\"wp-block-quote is-style-plain\\"><p>Quote content</p></blockquote>
33
+ <!-- /wp:quote -->"
34
+ ` );
31
35
  } );
32
36
  } );
@@ -12,6 +12,7 @@ import {
12
12
  activateTheme,
13
13
  canvas,
14
14
  createNewPost,
15
+ visitSiteEditor,
15
16
  saveDraft,
16
17
  insertBlock,
17
18
  } from '@wordpress/e2e-test-utils';
@@ -19,7 +20,6 @@ import {
19
20
  /**
20
21
  * Internal dependencies
21
22
  */
22
- import { siteEditor } from '../site-editor/utils';
23
23
  import {
24
24
  readFile,
25
25
  deleteFile,
@@ -83,8 +83,7 @@ describe( 'Site Editor Performance', () => {
83
83
  new URL( document.location ).searchParams.get( 'post' )
84
84
  );
85
85
 
86
- await siteEditor.visit( { postId: id, postType: 'page' } );
87
- await siteEditor.disableWelcomeGuide();
86
+ await visitSiteEditor( { postId: id, postType: 'page' } );
88
87
 
89
88
  let i = 3;
90
89
 
@@ -1,12 +1,11 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { trashAllPosts, activateTheme } from '@wordpress/e2e-test-utils';
5
-
6
- /**
7
- * Internal dependencies
8
- */
9
- import { siteEditor } from './utils';
4
+ import {
5
+ trashAllPosts,
6
+ activateTheme,
7
+ visitSiteEditor,
8
+ } from '@wordpress/e2e-test-utils';
10
9
 
11
10
  async function getDocumentSettingsTitle() {
12
11
  const titleElement = await page.waitForSelector(
@@ -35,14 +34,13 @@ describe( 'Document Settings', () => {
35
34
  } );
36
35
 
37
36
  beforeEach( async () => {
38
- await siteEditor.visit();
39
- await siteEditor.disableWelcomeGuide();
37
+ await visitSiteEditor();
40
38
  } );
41
39
 
42
40
  describe( 'when a template is selected from the navigation sidebar', () => {
43
41
  it( 'should display the selected templates name in the document header', async () => {
44
42
  // Navigate to a template
45
- await siteEditor.visit( {
43
+ await visitSiteEditor( {
46
44
  postId: 'emptytheme//index',
47
45
  postType: 'wp_template',
48
46
  } );
@@ -78,7 +76,7 @@ describe( 'Document Settings', () => {
78
76
  describe( 'when a template part is selected from the navigation sidebar', () => {
79
77
  it( "should display the selected template part's name in the document header", async () => {
80
78
  // Navigate to a template part
81
- await siteEditor.visit( {
79
+ await visitSiteEditor( {
82
80
  postId: 'emptytheme//header',
83
81
  postType: 'wp_template_part',
84
82
  } );
@@ -11,18 +11,18 @@ import {
11
11
  openDocumentSettingsSidebar,
12
12
  pressKeyWithModifier,
13
13
  selectBlockByClientId,
14
+ visitSiteEditor,
15
+ clickSiteEditorMenuItem,
16
+ navigateSiteEditorBackToRoot,
17
+ openSiteEditorNavigationPanel,
18
+ siteEditorNavigateSequence,
14
19
  } from '@wordpress/e2e-test-utils';
15
20
 
16
- /**
17
- * Internal dependencies
18
- */
19
- import { navigationPanel, siteEditor } from './utils';
20
-
21
21
  const clickTemplateItem = async ( menus, itemName ) => {
22
- await navigationPanel.open();
23
- await navigationPanel.backToRoot();
24
- await navigationPanel.navigate( menus );
25
- await navigationPanel.clickItemByText( itemName );
22
+ await openSiteEditorNavigationPanel();
23
+ await navigateSiteEditorBackToRoot();
24
+ await siteEditorNavigateSequence( menus );
25
+ await clickSiteEditorMenuItem( itemName );
26
26
  };
27
27
 
28
28
  const createTemplatePart = async (
@@ -144,14 +144,13 @@ describe( 'Multi-entity editor states', () => {
144
144
  } );
145
145
 
146
146
  it( 'should not display any dirty entities when loading the site editor', async () => {
147
- await siteEditor.visit();
148
- await siteEditor.disableWelcomeGuide();
147
+ await visitSiteEditor();
149
148
  expect( await openEntitySavePanel() ).toBe( false );
150
149
  } );
151
150
 
152
151
  // Skip reason: This should be rewritten to use other methods to switching to different templates.
153
152
  it.skip( 'should not dirty an entity by switching to it in the template dropdown', async () => {
154
- await siteEditor.visit( {
153
+ await visitSiteEditor( {
155
154
  postId: 'emptytheme//header',
156
155
  postType: 'wp_template_part',
157
156
  } );
@@ -204,8 +203,7 @@ describe( 'Multi-entity editor states', () => {
204
203
  true
205
204
  );
206
205
  await saveAllEntities();
207
- await siteEditor.visit();
208
- await siteEditor.disableWelcomeGuide();
206
+ await visitSiteEditor();
209
207
 
210
208
  // Wait for site editor to load.
211
209
  await canvas().waitForSelector(
@@ -12,13 +12,9 @@ import {
12
12
  activateTheme,
13
13
  clickButton,
14
14
  createReusableBlock,
15
+ visitSiteEditor,
15
16
  } from '@wordpress/e2e-test-utils';
16
17
 
17
- /**
18
- * Internal dependencies
19
- */
20
- import { siteEditor } from './utils';
21
-
22
18
  describe( 'Multi-entity save flow', () => {
23
19
  // Selectors - usable between Post/Site editors.
24
20
  const checkedBoxSelector = '.components-checkbox-control__checked';
@@ -263,11 +259,10 @@ describe( 'Multi-entity save flow', () => {
263
259
 
264
260
  it( 'Save flow should work as expected', async () => {
265
261
  // Navigate to site editor.
266
- await siteEditor.visit( {
262
+ await visitSiteEditor( {
267
263
  postId: 'emptytheme//index',
268
264
  postType: 'wp_template',
269
265
  } );
270
- await siteEditor.disableWelcomeGuide();
271
266
 
272
267
  // Select the header template part via list view.
273
268
  await page.click( '.edit-site-header-toolbar__list-view-toggle' );
@@ -301,11 +296,10 @@ describe( 'Multi-entity save flow', () => {
301
296
 
302
297
  it( 'Save flow should allow re-saving after changing the same block attribute', async () => {
303
298
  // Navigate to site editor.
304
- await siteEditor.visit( {
299
+ await visitSiteEditor( {
305
300
  postId: 'emptytheme//index',
306
301
  postType: 'wp_template',
307
302
  } );
308
- await siteEditor.disableWelcomeGuide();
309
303
 
310
304
  // Insert a paragraph at the bottom.
311
305
  await insertBlock( 'Paragraph' );
@@ -7,13 +7,9 @@ import {
7
7
  getAllBlocks,
8
8
  selectBlockByClientId,
9
9
  insertBlock,
10
+ visitSiteEditor,
10
11
  } from '@wordpress/e2e-test-utils';
11
12
 
12
- /**
13
- * Internal dependencies
14
- */
15
- import { siteEditor } from './utils';
16
-
17
13
  async function toggleSidebar() {
18
14
  await page.click(
19
15
  '.edit-site-header__actions button[aria-label="Settings"]'
@@ -52,8 +48,7 @@ describe( 'Settings sidebar', () => {
52
48
  await activateTheme( 'twentytwentyone' );
53
49
  } );
54
50
  beforeEach( async () => {
55
- await siteEditor.visit();
56
- await siteEditor.disableWelcomeGuide();
51
+ await visitSiteEditor();
57
52
  } );
58
53
 
59
54
  describe( 'Template tab', () => {
@@ -69,7 +64,7 @@ describe( 'Settings sidebar', () => {
69
64
  await toggleSidebar();
70
65
 
71
66
  const templateCardBeforeNavigation = await getTemplateCard();
72
- await siteEditor.visit( {
67
+ await visitSiteEditor( {
73
68
  postId: 'emptytheme//singular',
74
69
  postType: 'wp_template',
75
70
  } );
@@ -8,12 +8,12 @@ import os from 'os';
8
8
  /**
9
9
  * WordPress dependencies
10
10
  */
11
- import { trashAllPosts, activateTheme } from '@wordpress/e2e-test-utils';
12
-
13
- /**
14
- * Internal dependencies
15
- */
16
- import { siteEditor } from './utils';
11
+ import {
12
+ trashAllPosts,
13
+ activateTheme,
14
+ visitSiteEditor,
15
+ clickOnMoreMenuItem,
16
+ } from '@wordpress/e2e-test-utils';
17
17
 
18
18
  async function waitForFileExists( filePath, timeout = 10000 ) {
19
19
  const start = Date.now();
@@ -40,8 +40,7 @@ describe( 'Site Editor Templates Export', () => {
40
40
  } );
41
41
 
42
42
  beforeEach( async () => {
43
- await siteEditor.visit();
44
- await siteEditor.disableWelcomeGuide();
43
+ await visitSiteEditor();
45
44
  } );
46
45
 
47
46
  it( 'clicking export should download edit-site-export.zip file', async () => {
@@ -53,7 +52,7 @@ describe( 'Site Editor Templates Export', () => {
53
52
  downloadPath: directory,
54
53
  } );
55
54
 
56
- await siteEditor.clickOnMoreMenuItem( 'Export' );
55
+ await clickOnMoreMenuItem( 'Export', 'site-editor' );
57
56
  const filePath = path.join( directory, 'edit-site-export.zip' );
58
57
  await waitForFileExists( filePath );
59
58
  expect( fs.existsSync( filePath ) ).toBe( true );
@@ -1,12 +1,11 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { trashAllPosts, activateTheme } from '@wordpress/e2e-test-utils';
5
-
6
- /**
7
- * Internal dependencies
8
- */
9
- import { siteEditor } from './utils';
4
+ import {
5
+ trashAllPosts,
6
+ activateTheme,
7
+ visitSiteEditor,
8
+ } from '@wordpress/e2e-test-utils';
10
9
 
11
10
  describe( 'Site Editor Inserter', () => {
12
11
  beforeAll( async () => {
@@ -18,8 +17,7 @@ describe( 'Site Editor Inserter', () => {
18
17
  await activateTheme( 'twentytwentyone' );
19
18
  } );
20
19
  beforeEach( async () => {
21
- await siteEditor.visit();
22
- await siteEditor.disableWelcomeGuide();
20
+ await visitSiteEditor();
23
21
  } );
24
22
 
25
23
  it( 'inserter toggle button should toggle global inserter', async () => {
@@ -0,0 +1,211 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import {
5
+ trashAllPosts,
6
+ activateTheme,
7
+ visitSiteEditor,
8
+ toggleGlobalStyles,
9
+ openGlobalStylesPanel,
10
+ openPreviousGlobalStylesPanel,
11
+ } from '@wordpress/e2e-test-utils';
12
+
13
+ async function openOtherStyles() {
14
+ const OTHER_STYLES_SELECTOR = '//div[contains(text(),"Other styles")]';
15
+ await ( await page.waitForXPath( OTHER_STYLES_SELECTOR ) ).click();
16
+ }
17
+
18
+ async function getAvailableStyleVariations() {
19
+ const VARIATION_ITEMS_STYLES_SELECTOR =
20
+ '.edit-site-global-styles-variations_item';
21
+ await page.waitForSelector( VARIATION_ITEMS_STYLES_SELECTOR );
22
+ return page.$$( VARIATION_ITEMS_STYLES_SELECTOR );
23
+ }
24
+
25
+ async function applyVariation( number ) {
26
+ await toggleGlobalStyles();
27
+ await openOtherStyles();
28
+ const variations = await getAvailableStyleVariations();
29
+ await variations[ number ].click();
30
+ }
31
+
32
+ async function applyPinkVariation() {
33
+ await applyVariation( 1 );
34
+ }
35
+
36
+ async function applyYellowVariation() {
37
+ await applyVariation( 2 );
38
+ }
39
+
40
+ async function openColorsPanel() {
41
+ await openGlobalStylesPanel( 'Colors' );
42
+ }
43
+
44
+ async function openTypographyPanel() {
45
+ await openGlobalStylesPanel( 'Typography' );
46
+ }
47
+
48
+ async function openTextPanel() {
49
+ await openGlobalStylesPanel( 'Text' );
50
+ }
51
+
52
+ async function openPalettePanel() {
53
+ const selector = `//div[./h2[text()="Palette"]]//button`;
54
+ await ( await page.waitForXPath( selector ) ).click();
55
+ }
56
+
57
+ async function getFontSizeHint() {
58
+ const element = await page.$(
59
+ '.components-font-size-picker__header__hint'
60
+ );
61
+ return element.evaluate( ( el ) => el.textContent );
62
+ }
63
+
64
+ async function getCustomFontSizeValue() {
65
+ const element = await page.$(
66
+ '.components-font-size-picker input[aria-label="Custom"]'
67
+ );
68
+ return element.evaluate( ( el ) => el.value );
69
+ }
70
+
71
+ async function getColorValue( colorType ) {
72
+ return page.evaluate( ( _colorType ) => {
73
+ return document.evaluate(
74
+ `substring-before(substring-after(//div[@aria-label="Settings"]//button[.//*[text()="${ _colorType }"]]//*[contains(@class,"component-color-indicator")]/@style, "background: "), ";")`,
75
+ document,
76
+ null,
77
+ XPathResult.ANY_TYPE,
78
+ null
79
+ ).stringValue;
80
+ }, colorType );
81
+ }
82
+
83
+ async function getBackgroundColorValue() {
84
+ return getColorValue( 'Background' );
85
+ }
86
+
87
+ async function getTextColorValue() {
88
+ return getColorValue( 'Text' );
89
+ }
90
+
91
+ async function getColorPalette( paletteSource ) {
92
+ const paletteOptions = await page.$x(
93
+ `//div[./*/h2[text()="${ paletteSource }"]]//button[contains(@class,"components-circular-option-picker__option")]`
94
+ );
95
+ return Promise.all(
96
+ paletteOptions.map( ( element ) => {
97
+ return element.evaluate( ( el ) => {
98
+ const color = el.style.backgroundColor;
99
+ const name = el
100
+ .getAttribute( 'aria-label' )
101
+ .substring( 'Color: '.length );
102
+ return { color, name };
103
+ } );
104
+ } )
105
+ );
106
+ }
107
+
108
+ async function getThemePalette() {
109
+ return getColorPalette( 'Theme' );
110
+ }
111
+
112
+ describe( 'Global styles variations', () => {
113
+ beforeAll( async () => {
114
+ await activateTheme( 'gutenberg-test-themes/style-variations' );
115
+ await trashAllPosts( 'wp_template' );
116
+ await trashAllPosts( 'wp_template_part' );
117
+ } );
118
+ afterAll( async () => {
119
+ await activateTheme( 'twentytwentyone' );
120
+ } );
121
+ beforeEach( async () => {
122
+ await visitSiteEditor();
123
+ } );
124
+
125
+ it( 'Should have three variations available with the first one being active', async () => {
126
+ await toggleGlobalStyles();
127
+ await openOtherStyles();
128
+ const variations = await getAvailableStyleVariations();
129
+ expect( variations ).toHaveLength( 3 );
130
+ expect(
131
+ await (
132
+ await variations[ 0 ].getProperty( 'className' )
133
+ ).jsonValue()
134
+ ).toContain( 'is-active' );
135
+ expect(
136
+ await (
137
+ await variations[ 1 ].getProperty( 'className' )
138
+ ).jsonValue()
139
+ ).not.toContain( 'is-active' );
140
+ expect(
141
+ await (
142
+ await variations[ 2 ].getProperty( 'className' )
143
+ ).jsonValue()
144
+ ).not.toContain( 'is-active' );
145
+ } );
146
+
147
+ it( 'Should apply preset colors and font sizes in a variation', async () => {
148
+ await applyPinkVariation();
149
+ await openPreviousGlobalStylesPanel();
150
+ await openColorsPanel();
151
+ expect( await getBackgroundColorValue() ).toBe( 'rgb(202, 105, 211)' );
152
+ expect( await getTextColorValue() ).toBe( 'rgb(74, 7, 74)' );
153
+ await openPreviousGlobalStylesPanel();
154
+ await openTypographyPanel();
155
+ await openTextPanel();
156
+ expect( await getFontSizeHint() ).toBe( 'Medium(px)' );
157
+ } );
158
+
159
+ it( 'Should apply custom colors and font sizes in a variation', async () => {
160
+ await applyYellowVariation();
161
+ await openPreviousGlobalStylesPanel();
162
+ await openColorsPanel();
163
+ expect( await getBackgroundColorValue() ).toBe( 'rgb(255, 239, 11)' );
164
+ expect( await getTextColorValue() ).toBe( 'rgb(25, 25, 17)' );
165
+ await openPreviousGlobalStylesPanel();
166
+ await openTypographyPanel();
167
+ await openTextPanel();
168
+ expect( await getFontSizeHint() ).toBe( '(Custom)' );
169
+ expect( await getCustomFontSizeValue() ).toBe( '15' );
170
+ } );
171
+
172
+ it( 'Should apply a color palette in a variation', async () => {
173
+ await applyPinkVariation();
174
+ await openPreviousGlobalStylesPanel();
175
+ await openColorsPanel();
176
+ await openPalettePanel();
177
+ expect( await getThemePalette() ).toMatchObject( [
178
+ {
179
+ color: 'rgb(74, 7, 74)',
180
+ name: 'Foreground',
181
+ },
182
+ {
183
+ color: 'rgb(202, 105, 211)',
184
+ name: 'Background',
185
+ },
186
+ {
187
+ color: 'rgba(204, 0, 255, 0.77)',
188
+ name: 'Awesome pink',
189
+ },
190
+ ] );
191
+ } );
192
+
193
+ it( 'Should reflect style variations in the styles applied to the editor', async () => {
194
+ await applyYellowVariation();
195
+ const frame = await (
196
+ await page.waitForSelector( '.edit-site-visual-editor iframe' )
197
+ ).contentFrame();
198
+ const paragraph = await frame.waitForXPath(
199
+ `//p[text()="My awesome paragraph"]`
200
+ );
201
+ const paragraphColor = await paragraph.evaluate( ( el ) => {
202
+ return window.getComputedStyle( el ).color;
203
+ } );
204
+ expect( paragraphColor ).toBe( 'rgb(25, 25, 17)' );
205
+ const body = await frame.$( 'body' );
206
+ const backgroundColor = await body.evaluate( ( el ) => {
207
+ return window.getComputedStyle( el ).backgroundColor;
208
+ } );
209
+ expect( backgroundColor ).toBe( 'rgb(255, 239, 11)' );
210
+ } );
211
+ } );