diff --git a/.wp-env.json b/.wp-env.json
index 86e72e0964232..aa8dfaf3c0c4a 100644
--- a/.wp-env.json
+++ b/.wp-env.json
@@ -8,7 +8,7 @@
"wp-content/plugins/gutenberg": ".",
"wp-content/mu-plugins": "./packages/e2e-tests/mu-plugins",
"wp-content/plugins/gutenberg-test-plugins": "./packages/e2e-tests/plugins",
- "wp-content/themes/gutenberg-test-themes": "./packages/e2e-tests/themes"
+ "wp-content/themes/gutenberg-test-themes": "./test/gutenberg-test-themes"
}
}
}
diff --git a/packages/e2e-test-utils-playwright/src/editor/site-editor.ts b/packages/e2e-test-utils-playwright/src/editor/site-editor.ts
index 1b218bd7b3af3..9ea4fdeb0675e 100644
--- a/packages/e2e-test-utils-playwright/src/editor/site-editor.ts
+++ b/packages/e2e-test-utils-playwright/src/editor/site-editor.ts
@@ -23,6 +23,6 @@ export async function saveSiteEditorEntities( this: Editor ) {
// not have that classname.
// TODO - find a way to improve this selector to use role/name.
await this.page.waitForSelector(
- '.edit-site-save-button__button:not(.is-busy)'
+ 'css=.edit-site-save-button__button:not(.is-busy)'
);
}
diff --git a/packages/e2e-test-utils-playwright/src/request-utils/themes.ts b/packages/e2e-test-utils-playwright/src/request-utils/themes.ts
index 1bbb7fb410b49..bb2fbd8978159 100644
--- a/packages/e2e-test-utils-playwright/src/request-utils/themes.ts
+++ b/packages/e2e-test-utils-playwright/src/request-utils/themes.ts
@@ -13,9 +13,9 @@ async function activateTheme(
let response = await this.request.get( THEMES_URL );
const html = await response.text();
const matchGroup = html.match(
- new RegExp(
- `action=activate&stylesheet=${ themeSlug }&_wpnonce=[a-z0-9]+`
- )
+ `action=activate&stylesheet=${ encodeURIComponent(
+ themeSlug
+ ) }&_wpnonce=[a-z0-9]+`
);
if ( ! matchGroup ) {
diff --git a/packages/e2e-tests/specs/site-editor/style-variations.test.js b/packages/e2e-tests/specs/site-editor/style-variations.test.js
deleted file mode 100644
index 16f50fdf9154c..0000000000000
--- a/packages/e2e-tests/specs/site-editor/style-variations.test.js
+++ /dev/null
@@ -1,213 +0,0 @@
-/**
- * WordPress dependencies
- */
-import {
- trashAllPosts,
- activateTheme,
- visitSiteEditor,
- toggleGlobalStyles,
- openGlobalStylesPanel,
- openPreviousGlobalStylesPanel,
-} from '@wordpress/e2e-test-utils';
-
-async function openOtherStyles() {
- const OTHER_STYLES_SELECTOR = '//div[contains(text(),"Browse styles")]';
- await ( await page.waitForXPath( OTHER_STYLES_SELECTOR ) ).click();
-}
-
-async function getAvailableStyleVariations() {
- const VARIATION_ITEMS_STYLES_SELECTOR =
- '.edit-site-global-styles-variations_item';
- await page.waitForSelector( VARIATION_ITEMS_STYLES_SELECTOR );
- return page.$$( VARIATION_ITEMS_STYLES_SELECTOR );
-}
-
-async function applyVariation( label ) {
- await toggleGlobalStyles();
- await openOtherStyles();
- const variation = await page.waitForXPath(
- `//*[@role="button"][@aria-label="${ label }"]`
- );
- await variation.click();
-}
-
-async function applyPinkVariation() {
- await applyVariation( 'pink' );
-}
-
-async function applyYellowVariation() {
- await applyVariation( 'yellow' );
-}
-
-async function openColorsPanel() {
- await openGlobalStylesPanel( 'Colors' );
-}
-
-async function openTypographyPanel() {
- await openGlobalStylesPanel( 'Typography' );
-}
-
-async function openTextPanel() {
- await openGlobalStylesPanel( 'Text' );
-}
-
-async function openPalettePanel() {
- const selector = `//div[./h2[text()="Palette"]]//button`;
- await ( await page.waitForXPath( selector ) ).click();
-}
-
-async function getFontSizeHint() {
- const element = await page.$(
- '.components-font-size-picker__header__hint'
- );
- return element.evaluate( ( el ) => el.textContent );
-}
-
-async function getCustomFontSizeValue() {
- const element = await page.$(
- '.components-font-size-picker input[aria-label="Custom"]'
- );
- return element.evaluate( ( el ) => el.value );
-}
-
-async function getColorValue( colorType ) {
- return page.evaluate( ( _colorType ) => {
- return document.evaluate(
- `substring-before(substring-after(//div[contains(@class, "edit-site-global-styles-sidebar__panel")]//button[.//*[text()="${ _colorType }"]]//*[contains(@class,"component-color-indicator")]/@style, "background: "), ";")`,
- document,
- null,
- XPathResult.ANY_TYPE,
- null
- ).stringValue;
- }, colorType );
-}
-
-async function getBackgroundColorValue() {
- return getColorValue( 'Background' );
-}
-
-async function getTextColorValue() {
- return getColorValue( 'Text' );
-}
-
-async function getColorPalette( paletteSource ) {
- const paletteOptions = await page.$x(
- `//div[./*/h2[text()="${ paletteSource }"]]//button[contains(@class,"components-circular-option-picker__option")]`
- );
- return Promise.all(
- paletteOptions.map( ( element ) => {
- return element.evaluate( ( el ) => {
- const color = el.style.backgroundColor;
- const name = el
- .getAttribute( 'aria-label' )
- .substring( 'Color: '.length );
- return { color, name };
- } );
- } )
- );
-}
-
-async function getThemePalette() {
- return getColorPalette( 'Theme' );
-}
-
-describe( 'Global styles variations', () => {
- beforeAll( async () => {
- await activateTheme( 'gutenberg-test-themes/style-variations' );
- await trashAllPosts( 'wp_template' );
- await trashAllPosts( 'wp_template_part' );
- } );
- afterAll( async () => {
- await activateTheme( 'twentytwentyone' );
- } );
- beforeEach( async () => {
- await visitSiteEditor();
- } );
-
- it( 'Should have three variations available with the first one being active', async () => {
- await toggleGlobalStyles();
- await openOtherStyles();
- const variations = await getAvailableStyleVariations();
- expect( variations ).toHaveLength( 3 );
- expect(
- await (
- await variations[ 0 ].getProperty( 'className' )
- ).jsonValue()
- ).toContain( 'is-active' );
- expect(
- await (
- await variations[ 1 ].getProperty( 'className' )
- ).jsonValue()
- ).not.toContain( 'is-active' );
- expect(
- await (
- await variations[ 2 ].getProperty( 'className' )
- ).jsonValue()
- ).not.toContain( 'is-active' );
- } );
-
- it( 'Should apply preset colors and font sizes in a variation', async () => {
- await applyPinkVariation();
- await openPreviousGlobalStylesPanel();
- await openColorsPanel();
- expect( await getBackgroundColorValue() ).toBe( 'rgb(202, 105, 211)' );
- expect( await getTextColorValue() ).toBe( 'rgb(74, 7, 74)' );
- await openPreviousGlobalStylesPanel();
- await openTypographyPanel();
- await openTextPanel();
- expect( await getFontSizeHint() ).toBe( 'Medium(px)' );
- } );
-
- it( 'Should apply custom colors and font sizes in a variation', async () => {
- await applyYellowVariation();
- await openPreviousGlobalStylesPanel();
- await openColorsPanel();
- expect( await getBackgroundColorValue() ).toBe( 'rgb(255, 239, 11)' );
- expect( await getTextColorValue() ).toBe( 'rgb(25, 25, 17)' );
- await openPreviousGlobalStylesPanel();
- await openTypographyPanel();
- await openTextPanel();
- expect( await getFontSizeHint() ).toBe( '(Custom)' );
- expect( await getCustomFontSizeValue() ).toBe( '15' );
- } );
-
- it( 'Should apply a color palette in a variation', async () => {
- await applyPinkVariation();
- await openPreviousGlobalStylesPanel();
- await openColorsPanel();
- await openPalettePanel();
- expect( await getThemePalette() ).toMatchObject( [
- {
- color: 'rgb(74, 7, 74)',
- name: 'Foreground',
- },
- {
- color: 'rgb(202, 105, 211)',
- name: 'Background',
- },
- {
- color: 'rgba(204, 0, 255, 0.77)',
- name: 'Awesome pink',
- },
- ] );
- } );
-
- it( 'Should reflect style variations in the styles applied to the editor', async () => {
- await applyYellowVariation();
- const frame = await (
- await page.waitForSelector( '.edit-site-visual-editor iframe' )
- ).contentFrame();
- const paragraph = await frame.waitForXPath(
- `//p[text()="My awesome paragraph"]`
- );
- const paragraphColor = await paragraph.evaluate( ( el ) => {
- return window.getComputedStyle( el ).color;
- } );
- expect( paragraphColor ).toBe( 'rgb(25, 25, 17)' );
- const body = await frame.$( 'body' );
- const backgroundColor = await body.evaluate( ( el ) => {
- return window.getComputedStyle( el ).backgroundColor;
- } );
- expect( backgroundColor ).toBe( 'rgb(255, 239, 11)' );
- } );
-} );
diff --git a/packages/edit-site/src/components/global-styles/context-menu.js b/packages/edit-site/src/components/global-styles/context-menu.js
index e33aa99fe8195..19a252763ff7e 100644
--- a/packages/edit-site/src/components/global-styles/context-menu.js
+++ b/packages/edit-site/src/components/global-styles/context-menu.js
@@ -27,6 +27,7 @@ function ContextMenu( { name, parentMenu = '' } ) {
{ __( 'Typography' ) }
@@ -35,6 +36,7 @@ function ContextMenu( { name, parentMenu = '' } ) {
{ __( 'Colors' ) }
@@ -43,6 +45,7 @@ function ContextMenu( { name, parentMenu = '' } ) {
{ __( 'Layout' ) }
diff --git a/packages/edit-site/src/components/global-styles/palette.js b/packages/edit-site/src/components/global-styles/palette.js
index c0c1d0968832a..dd7bff6fd2ee6 100644
--- a/packages/edit-site/src/components/global-styles/palette.js
+++ b/packages/edit-site/src/components/global-styles/palette.js
@@ -58,7 +58,10 @@ function Palette( { name } ) {
{ __( 'Palette' ) }
-
+
+
{ block.title }
diff --git a/packages/edit-site/src/components/global-styles/screen-colors.js b/packages/edit-site/src/components/global-styles/screen-colors.js
index 4e961dcf0e75b..78607e0d1997f 100644
--- a/packages/edit-site/src/components/global-styles/screen-colors.js
+++ b/packages/edit-site/src/components/global-styles/screen-colors.js
@@ -33,11 +33,15 @@ function BackgroundColorItem( { name, parentMenu } ) {
}
return (
-
+
{ __( 'Background' ) }
@@ -56,10 +60,16 @@ function TextColorItem( { name, parentMenu } ) {
}
return (
-
+
-
+
{ __( 'Text' ) }
@@ -77,7 +87,10 @@ function LinkColorItem( { name, parentMenu } ) {
}
return (
-
+
diff --git a/packages/edit-site/src/components/global-styles/screen-root.js b/packages/edit-site/src/components/global-styles/screen-root.js
index da8c13d28f017..0674b56319c70 100644
--- a/packages/edit-site/src/components/global-styles/screen-root.js
+++ b/packages/edit-site/src/components/global-styles/screen-root.js
@@ -46,7 +46,10 @@ function ScreenRoot() {
{ !! variations?.length && (
-
+
{ __( 'Browse styles' ) }
@@ -82,7 +85,10 @@ function ScreenRoot() {
) }
-
+
{ __( 'Blocks' ) }
+
{
+ await use( new SiteEditorStyleVariations( { page } ) );
+ },
+} );
+
+test.describe( 'Global styles variations', () => {
+ test.beforeAll( async ( { requestUtils } ) => {
+ await requestUtils.activateTheme(
+ 'gutenberg-test-themes/style-variations'
+ );
+ await requestUtils.deleteAllTemplates( 'wp_template' );
+ await requestUtils.deleteAllTemplates( 'wp_template_part' );
+ } );
+
+ test.afterEach( async ( { requestUtils } ) => {
+ await Promise.all( [
+ requestUtils.deleteAllTemplates( 'wp_template' ),
+ requestUtils.deleteAllTemplates( 'wp_template_part' ),
+ ] );
+ } );
+
+ test.afterAll( async ( { requestUtils } ) => {
+ await requestUtils.activateTheme( 'twentytwentyone' );
+ } );
+
+ test( 'should have three variations available with the first one being active', async ( {
+ admin,
+ page,
+ siteEditorStyleVariations,
+ } ) => {
+ await admin.visitSiteEditor( {
+ postId: 'gutenberg-test-themes/style-variations//index',
+ postType: 'wp_template',
+ } );
+
+ await siteEditorStyleVariations.browseStyles();
+
+ // TODO: instead of locating these elements by class,
+ // we could update the source code to group them in a or other container,
+ // then add `aria-labelledby` and `aria-describedby` etc to provide accessible information,
+ const variations = page.locator(
+ '.edit-site-global-styles-variations_item'
+ );
+
+ await expect( variations ).toHaveCount( 3 );
+
+ await expect( variations.first() ).toHaveAttribute(
+ 'aria-current',
+ 'true'
+ );
+ await expect( variations.nth( 1 ) ).toHaveAttribute(
+ 'aria-current',
+ 'false'
+ );
+ await expect( variations.nth( 2 ) ).toHaveAttribute(
+ 'aria-current',
+ 'false'
+ );
+ } );
+
+ test( 'should apply preset colors and font sizes in a variation', async ( {
+ admin,
+ page,
+ siteEditorStyleVariations,
+ } ) => {
+ await admin.visitSiteEditor( {
+ postId: 'gutenberg-test-themes/style-variations//index',
+ postType: 'wp_template',
+ } );
+ await siteEditorStyleVariations.browseStyles();
+ await page.click( 'role=button[name="pink"i]' );
+ await page.click(
+ 'role=button[name="Navigate to the previous view"i]'
+ );
+ await page.click( 'role=button[name="Colors styles"i]' );
+
+ await expect(
+ page.locator(
+ 'role=button[name="Colors background styles"i] >> data-testid=background-color-indicator'
+ )
+ ).toHaveCSS( 'background', /rgb\(202, 105, 211\)/ );
+
+ await expect(
+ page.locator(
+ 'role=button[name="Colors text styles"i] >> data-testid=text-color-indicator'
+ )
+ ).toHaveCSS( 'background', /rgb\(74, 7, 74\)/ );
+
+ await page.click(
+ 'role=button[name="Navigate to the previous view"i]'
+ );
+ await page.click( 'role=button[name="Typography styles"i]' );
+ await page.click( 'role=button[name="Typography Text styles"i]' );
+
+ await expect(
+ page.locator( 'css=.components-font-size-picker__header__hint' )
+ ).toHaveText( 'Medium(px)' );
+ } );
+
+ test( 'should apply custom colors and font sizes in a variation', async ( {
+ admin,
+ page,
+ siteEditorStyleVariations,
+ } ) => {
+ await admin.visitSiteEditor( {
+ postId: 'gutenberg-test-themes/style-variations//index',
+ postType: 'wp_template',
+ } );
+ await siteEditorStyleVariations.browseStyles();
+ await page.click( 'role=button[name="yellow"i]' );
+ await page.click(
+ 'role=button[name="Navigate to the previous view"i]'
+ );
+ await page.click( 'role=button[name="Colors styles"i]' );
+
+ await expect(
+ page.locator(
+ 'role=button[name="Colors background styles"i] >> data-testid=background-color-indicator'
+ )
+ ).toHaveCSS( 'background', /rgb\(255, 239, 11\)/ );
+
+ await expect(
+ page.locator(
+ 'role=button[name="Colors text styles"i] >> data-testid=text-color-indicator'
+ )
+ ).toHaveCSS( 'background', /rgb\(25, 25, 17\)/ );
+
+ await page.click(
+ 'role=button[name="Navigate to the previous view"i]'
+ );
+ await page.click( 'role=button[name="Typography styles"i]' );
+ await page.click( 'role=button[name="Typography Text styles"i]' );
+
+ // TODO: to avoid use classnames to locate these elements,
+ // we could provide accessible attributes to the source code in packages/components/src/font-size-picker/index.js.
+ await expect(
+ page.locator( 'css=.components-font-size-picker__header__hint' )
+ ).toHaveText( '(Custom)' );
+
+ await expect(
+ page.locator( 'role=spinbutton[name="Custom"i]' )
+ ).toHaveValue( '15' );
+ } );
+
+ test( 'should apply a color palette in a variation', async ( {
+ admin,
+ page,
+ siteEditorStyleVariations,
+ } ) => {
+ await admin.visitSiteEditor( {
+ postId: 'gutenberg-test-themes/style-variations//index',
+ postType: 'wp_template',
+ } );
+ await siteEditorStyleVariations.browseStyles();
+ await page.click( 'role=button[name="pink"i]' );
+ await page.click(
+ 'role=button[name="Navigate to the previous view"i]'
+ );
+ await page.click( 'role=button[name="Colors styles"i]' );
+ await page.click( 'role=button[name="Color palettes"i]' );
+
+ await expect(
+ page.locator( 'role=button[name="Color: Foreground"i]' )
+ ).toHaveCSS( 'background-color', 'rgb(74, 7, 74)' );
+
+ await expect(
+ page.locator( 'role=button[name="Color: Background"i]' )
+ ).toHaveCSS( 'background-color', 'rgb(202, 105, 211)' );
+
+ await expect(
+ page.locator( 'role=button[name="Color: Awesome pink"i]' )
+ ).toHaveCSS( 'background-color', 'rgba(204, 0, 255, 0.77)' );
+ } );
+
+ test( 'should reflect style variations in the styles applied to the editor', async ( {
+ admin,
+ page,
+ siteEditorStyleVariations,
+ } ) => {
+ await admin.visitSiteEditor( {
+ postId: 'gutenberg-test-themes/style-variations//index',
+ postType: 'wp_template',
+ } );
+ await siteEditorStyleVariations.browseStyles();
+ await page.click( 'role=button[name="yellow"i]' );
+
+ const frame = page.frame( 'editor-canvas' );
+ const paragraph = frame.locator( 'text="My awesome paragraph"' );
+ await expect( paragraph ).toHaveCSS( 'color', 'rgb(25, 25, 17)' );
+
+ const body = frame.locator( 'css=body' );
+ await expect( body ).toHaveCSS(
+ 'background-color',
+ 'rgb(255, 239, 11)'
+ );
+ } );
+} );
+
+class SiteEditorStyleVariations {
+ constructor( { page } ) {
+ this.page = page;
+ }
+
+ async disableWelcomeGuide() {
+ // Turn off the welcome guide.
+ await this.page.evaluate( () => {
+ window.wp.data
+ .dispatch( 'core/preferences' )
+ .set( 'core/edit-site', 'welcomeGuideStyles', false );
+ } );
+ }
+
+ async browseStyles() {
+ await this.disableWelcomeGuide();
+ await this.page.click( 'role=button[name="Styles"i]' );
+ await this.page.click( 'role=button[name="Browse styles"i]' );
+ }
+}
diff --git a/packages/e2e-tests/themes/style-variations/block-templates/index.html b/test/gutenberg-test-themes/style-variations/block-templates/index.html
similarity index 100%
rename from packages/e2e-tests/themes/style-variations/block-templates/index.html
rename to test/gutenberg-test-themes/style-variations/block-templates/index.html
diff --git a/packages/e2e-tests/themes/style-variations/index.php b/test/gutenberg-test-themes/style-variations/index.php
similarity index 100%
rename from packages/e2e-tests/themes/style-variations/index.php
rename to test/gutenberg-test-themes/style-variations/index.php
diff --git a/packages/e2e-tests/themes/style-variations/style.css b/test/gutenberg-test-themes/style-variations/style.css
similarity index 100%
rename from packages/e2e-tests/themes/style-variations/style.css
rename to test/gutenberg-test-themes/style-variations/style.css
diff --git a/packages/e2e-tests/themes/style-variations/styles/pink.json b/test/gutenberg-test-themes/style-variations/styles/pink.json
similarity index 100%
rename from packages/e2e-tests/themes/style-variations/styles/pink.json
rename to test/gutenberg-test-themes/style-variations/styles/pink.json
diff --git a/packages/e2e-tests/themes/style-variations/styles/yellow.json b/test/gutenberg-test-themes/style-variations/styles/yellow.json
similarity index 100%
rename from packages/e2e-tests/themes/style-variations/styles/yellow.json
rename to test/gutenberg-test-themes/style-variations/styles/yellow.json
diff --git a/packages/e2e-tests/themes/style-variations/theme.json b/test/gutenberg-test-themes/style-variations/theme.json
similarity index 100%
rename from packages/e2e-tests/themes/style-variations/theme.json
rename to test/gutenberg-test-themes/style-variations/theme.json