Skip to content

Commit

Permalink
Adding some explanatory comments
Browse files Browse the repository at this point in the history
Add rudimentary E2E test covering block style partials, applying them, updating them and viewing styles revisions.
  • Loading branch information
ramonjd committed Jun 27, 2024
1 parent b9eb758 commit fcebc07
Show file tree
Hide file tree
Showing 6 changed files with 369 additions and 0 deletions.
4 changes: 4 additions & 0 deletions packages/block-editor/src/hooks/block-style-variation.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ function getVariationNameFromClass( className, registeredStyles = [] ) {
return null;
}

// A helper component to apply a style override using the useStyleOverride hook.
function OverrideStyles( { override } ) {
useStyleOverride( override );
}
Expand All @@ -69,6 +70,9 @@ function OverrideStyles( { override } ) {
* based on an incoming theme config. If a matching style is found in the config,
* a new override is created and returned. The overrides can be used in conjunction with
* useStyleOverride to apply the new styles to the editor.
* NOTE: This component is required to load global styles revisions config. Style variation overrides are
* generated using the canvas's current global styles (see useBlockStyleVariation()). This component is,
* however, due to be refactored and therefore it's use elsewhere is not recommended.
*
* @param {Object} props Props.
* @param {Object} props.config A global styles object, containing settings and styles.
Expand Down
303 changes: 303 additions & 0 deletions test/e2e/specs/site-editor/block-style-variations.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
/**
* WordPress dependencies
*/
const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' );
const TEST_PAGE_TITLE = 'Test Page for Block Style Variations';
test.use( {
siteEditorBlockStyleVariations: async ( { page, editor }, use ) => {
await use( new SiteEditorBlockStyleVariations( { page, editor } ) );
},
} );

test.describe( 'Block Style Variations', () => {
let stylesPostId;
test.beforeAll( async ( { requestUtils } ) => {
await Promise.all( [
requestUtils.activateTheme(
'gutenberg-test-themes/style-variations'
),
requestUtils.deleteAllPages(),
] );
stylesPostId = await requestUtils.getCurrentThemeGlobalStylesPostId();
} );

test.afterAll( async ( { requestUtils } ) => {
await Promise.all( [
requestUtils.activateTheme( 'twentytwentyone' ),
requestUtils.deleteAllPages(),
] );
} );

test.beforeEach( async ( { requestUtils, admin } ) => {
await Promise.all( [
requestUtils.deleteAllPages(),
admin.visitSiteEditor(),
] );
} );

test( 'apply block styles variations to nested blocks', async ( {
editor,
page,
} ) => {
await draftNewPage( page );
await addPageContent( editor, page );
const firstGroup = editor.canvas
.locator( '[data-type="core/group"]' )
.first();
const secondGroup = editor.canvas
.locator( '[data-type="core/group"]' )
.nth( 1 );
const thirdGroup = editor.canvas
.locator( '[data-type="core/group"]' )
.nth( 2 );

// Apply a block style to the parent Group block.
await editor.selectBlocks( firstGroup );
await editor.openDocumentSettingsSidebar();
await page.getByRole( 'tab', { name: 'Styles' } ).click();
await page
.getByRole( 'button', { name: 'Block Style Variation A' } )
.click( { force: true } );

// Check parent styles.
await expect( firstGroup ).toHaveCSS( 'border-style', 'dotted' );
await expect( firstGroup ).toHaveCSS( 'border-width', '1px' );

// Check nested child and grandchild group block inherited styles.
await expect( secondGroup ).toHaveCSS( 'border-style', 'solid' );
await expect( secondGroup ).toHaveCSS( 'border-width', '11px' );
await expect( thirdGroup ).toHaveCSS( 'border-style', 'solid' );
await expect( thirdGroup ).toHaveCSS( 'border-width', '11px' );

// Apply a block style to the first, nested Group block.
await editor.selectBlocks( secondGroup );
await page.getByRole( 'tab', { name: 'Styles' } ).click();
await page
.getByRole( 'button', { name: 'Block Style Variation B' } )
.click( { force: true } );

// Check nested child styles.
await expect( secondGroup ).toHaveCSS( 'border-style', 'dashed' );
await expect( secondGroup ).toHaveCSS( 'border-width', '2px' );

// Check nested grandchild group block inherited styles.
await expect( thirdGroup ).toHaveCSS( 'border-style', 'groove' );
await expect( thirdGroup ).toHaveCSS( 'border-width', '22px' );
} );

test( 'update block style variations in global styles and check revisions match styles', async ( {
editor,
page,
siteEditorBlockStyleVariations,
} ) => {
await draftNewPage( page );
await addPageContent( editor, page );
const firstGroup = editor.canvas
.locator( '[data-type="core/group"]' )
.first();
const secondGroup = editor.canvas
.locator( '[data-type="core/group"]' )
.nth( 1 );
const thirdGroup = editor.canvas
.locator( '[data-type="core/group"]' )
.nth( 2 );

// Apply a block style to the parent Group block.
await editor.selectBlocks( firstGroup );
await editor.openDocumentSettingsSidebar();
await page.getByRole( 'tab', { name: 'Styles' } ).click();
await page
.getByRole( 'button', { name: 'Block Style Variation A' } )
.click( { force: true } );

// Apply a block style to the first, nested Group block.
await editor.selectBlocks( secondGroup );
await page.getByRole( 'tab', { name: 'Styles' } ).click();
await page
.getByRole( 'button', { name: 'Block Style Variation B' } )
.click( { force: true } );

// Update user global styles with new block style variation values.
await siteEditorBlockStyleVariations.saveRevision( stylesPostId, {
blocks: {
'core/group': {
variations: {
'block-style-variation-a': {
border: {
width: '3px',
style: 'outset',
},
},
'block-style-variation-b': {
border: {
width: '4px',
style: 'double',
},
},
},
},
},
} );

// Check parent styles.
await expect( firstGroup ).toHaveCSS( 'border-style', 'outset' );
await expect( firstGroup ).toHaveCSS( 'border-width', '3px' );

// Check nested child styles.
await expect( secondGroup ).toHaveCSS( 'border-style', 'double' );
await expect( secondGroup ).toHaveCSS( 'border-width', '4px' );

// Check nested grandchild group block inherited styles.
await expect( thirdGroup ).toHaveCSS( 'border-style', 'groove' );
await expect( thirdGroup ).toHaveCSS( 'border-width', '22px' );

// The initial revision styles should match the editor canvas.
await siteEditorBlockStyleVariations.openStylesPanel();
const revisionsButton = page.getByRole( 'button', {
name: 'Revisions',
exact: true,
} );
await revisionsButton.click();
await expect(
page.locator( 'iframe[name="revisions"]' )
).toBeVisible();
const revisionIframe = page.frameLocator( '[name="revisions"]' );

const revisionFirstGroup = revisionIframe
.getByRole( 'document', {
name: 'Block: Content',
} )
.locator( '[data-type="core/group"]' )
.first();
const revisionSecondGroup = revisionIframe
.getByRole( 'document', {
name: 'Block: Content',
} )
.locator( '[data-type="core/group"]' )
.nth( 1 );
const revisionThirdGroup = revisionIframe
.getByRole( 'document', {
name: 'Block: Content',
} )
.locator( '[data-type="core/group"]' )
.nth( 2 );

// Check parent styles.
await expect( revisionFirstGroup ).toHaveCSS(
'border-style',
'outset'
);
await expect( revisionFirstGroup ).toHaveCSS( 'border-width', '3px' );

// Check nested child styles.
await expect( revisionSecondGroup ).toHaveCSS(
'border-style',
'double'
);
await expect( revisionSecondGroup ).toHaveCSS( 'border-width', '4px' );

// Check nested grandchild group block inherited styles.
await expect( revisionThirdGroup ).toHaveCSS(
'border-style',
'groove'
);
await expect( revisionThirdGroup ).toHaveCSS( 'border-width', '22px' );
} );
} );

class SiteEditorBlockStyleVariations {
constructor( { page, editor } ) {
this.page = page;
this.editor = editor;
}

async openStylesPanel() {
await this.page
.getByRole( 'region', { name: 'Editor top bar' } )
.getByRole( 'button', { name: 'Styles' } )
.click();
}

async saveRevision( stylesPostId, styles = {}, settings = {} ) {
await this.page.evaluate(
async ( [ _stylesPostId, _styles, _settings ] ) => {
window.wp.data
.dispatch( 'core' )
.editEntityRecord( 'root', 'globalStyles', _stylesPostId, {
id: _stylesPostId,
settings: _settings,
styles: _styles,
} );
},
[ stylesPostId, styles, settings ]
);
await this.editor.saveSiteEditorEntities();
}
}

async function draftNewPage( page ) {
await page.getByRole( 'button', { name: 'Pages' } ).click();
await page.getByRole( 'button', { name: 'Add new page' } ).click();
await page
.locator( 'role=dialog[name="Draft a new page"i]' )
.locator( 'role=textbox[name="Page title"i]' )
.fill( TEST_PAGE_TITLE );
await page.keyboard.press( 'Enter' );
await expect(
page.locator(
`role=button[name="Dismiss this notice"i] >> text='"${ TEST_PAGE_TITLE }" successfully created.'`
)
).toBeVisible();
}

// Create a Group block with 2 nested Group blocks.
async function addPageContent( editor, page ) {
const inserterButton = page.locator(
'role=button[name="Toggle block inserter"i]'
);
await inserterButton.click();
await page.type(
'role=searchbox[name="Search for blocks and patterns"i]',
'Group'
);
await page.click(
'role=listbox[name="Blocks"i] >> role=option[name="Group"i]'
);
await editor.canvas
.locator( 'role=button[name="Group: Gather blocks in a container."i]' )
.click();
await editor.canvas.locator( 'role=button[name="Add block"i]' ).click();
await page.click(
'role=listbox[name="Blocks"i] >> role=option[name="Paragraph"i]'
);
await page.keyboard.type( 'Parent Group Block with a Paragraph' );
await page.keyboard.press( 'Enter' );
await page.keyboard.type( '/group' );
await expect(
page.locator( 'role=option[name="Group"i][selected]' )
).toBeVisible();
await page.keyboard.press( 'Enter' );
await editor.canvas
.locator( 'role=button[name="Group: Gather blocks in a container."i]' )
.click();
await editor.canvas.locator( 'role=button[name="Add block"i]' ).click();
await page.click(
'role=listbox[name="Blocks"i] >> role=option[name="Paragraph"i]'
);
await page.keyboard.type( 'Child Group Block with a Paragraph' );
await page.keyboard.press( 'Enter' );
await page.keyboard.type( '/group' );
await expect(
page.locator( 'role=option[name="Group"i][selected]' )
).toBeVisible();
await page.keyboard.press( 'Enter' );
await editor.canvas
.locator( 'role=button[name="Group: Gather blocks in a container."i]' )
.click();
await editor.canvas.locator( 'role=button[name="Add block"i]' ).click();
await page.click(
'role=listbox[name="Blocks"i] >> role=option[name="Paragraph"i]'
);
await page.keyboard.type( 'Grandchild Group Block with a Paragraph' );
await page.getByRole( 'button', { name: 'Publish', exact: true } ).click();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<!-- wp:post-title /-->
<!-- wp:post-content {"layout":{"inherit":true}} /-->
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"version": 3,
"title": "Block Style Variation A",
"slug": "block-style-variation-a",
"blockTypes": [ "core/group" ],
"styles": {
"border": {
"width": "1px",
"style": "dotted"
},
"blocks": {
"core/group": {
"border": {
"width": "11px",
"style": "solid"
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"version": 3,
"title": "Block Style Variation B",
"slug": "block-style-variation-b",
"blockTypes": [ "core/group" ],
"styles": {
"border": {
"width": "2px",
"style": "dashed"
},
"blocks": {
"core/group": {
"border": {
"width": "22px",
"style": "groove"
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"version": 3,
"title": "Block Style Variation C",
"slug": "block-style-variation-c",
"blockTypes": [ "core/group" ],
"styles": {
"color": {
"background": "darkslateblue",
"text": "aliceblue"
},
"blocks": {
"core/group": {
"color": {
"background": "slateblue",
"text": "linen"
}
}
}
}
}

0 comments on commit fcebc07

Please sign in to comment.