diff --git a/changelog.txt b/changelog.txt index 2a1e7d62ed6568..9f6e6f652c2b02 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,6 @@ == Changelog == -= 20.3.0-rc.1 = - += 20.3.0 = ## Changelog @@ -90,6 +89,7 @@ #### Interactivity API - iAPI Router: Fix CSS rule order in some constructed style sheets. ([68923](https://github.com/WordPress/gutenberg/pull/68923)) +- iAPI Router: Revert "Handle styles assets on region-based navigation" ([69222](https://github.com/WordPress/gutenberg/pull/69222)) ### Accessibility diff --git a/docs/reference-guides/block-api/block-variations.md b/docs/reference-guides/block-api/block-variations.md index 8a0c6b1dd5bd6c..8c223e54eea299 100644 --- a/docs/reference-guides/block-api/block-variations.md +++ b/docs/reference-guides/block-api/block-variations.md @@ -60,6 +60,44 @@ wp.blocks.registerBlockVariation( 'core/embed', { } ); ``` +## Registering block variations in PHP + +Block variations can also be registered from PHP using the `get_block_type_variations` filter hook. This approach is particularly useful when you need to dynamically generate variations based on registered post types, taxonomies, or other WordPress data. + +Here's an example of how to register a custom variation for the `core/image` block: + +```php +function my_custom_image_variation( $variations, $block_type ) { + // Only modify variations for the image block + if ( 'core/image' !== $block_type->name ) { + return $variations; + } + + // Add a custom variation + $variations[] = array( + 'name' => 'wide-image', + 'title' => __( 'Wide image', 'textdomain' ), + 'description' => __( 'A wide image', 'textdomain' ), + 'scope' => array( 'inserter' ), + 'isDefault' => false, + 'attributes' => array( + 'align' => 'wide', // Identifies the link type as custom + ), + ); + + return $variations; +} +add_filter( 'get_block_type_variations', 'my_custom_image_variation', 10, 2 ); +``` + +The `get_block_type_variations` filter is called when variations are requested for a block type. It receives two parameters: +- `$variations`: An array of currently registered variations for the block type +- `$block_type`: The full block type object + +Note that variations registered through PHP will be merged with any variations registered through JavaScript using `registerBlockVariation()`. + +
Check the How to register block variations with PHP blog post for more info about this
+ ## Removing a block variation Block variations can also be easily removed. To do so, use `wp.blocks.unregisterBlockVariation()`. This function accepts the name of the block and the `name` of the variation that should be unregistered. diff --git a/gutenberg.php b/gutenberg.php index 58e04e0b9e4f54..58146500737685 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.6 * Requires PHP: 7.2 - * Version: 20.3.0-rc.1 + * Version: 20.3.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/package-lock.json b/package-lock.json index b5bd7ed6c1b7ef..a8bbafbfc2eb1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gutenberg", - "version": "20.3.0-rc.1", + "version": "20.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gutenberg", - "version": "20.3.0-rc.1", + "version": "20.3.0", "hasInstallScript": true, "license": "GPL-2.0-or-later", "workspaces": [ diff --git a/package.json b/package.json index 5459c72eb14728..0737c415f71c10 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gutenberg", - "version": "20.3.0-rc.1", + "version": "20.3.0", "private": true, "description": "A new WordPress editor experience.", "author": "The WordPress Contributors", diff --git a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap index 3d082a14a92bff..eb665ced62079f 100644 --- a/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap +++ b/packages/block-editor/src/components/color-palette/test/__snapshots__/control.js.snap @@ -203,7 +203,7 @@ exports[`ColorPaletteControl matches the snapshot 1`] = ` class="components-circular-option-picker" >
diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index 3ae01525a80109..8411430dfbdadd 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -131,8 +131,23 @@ function Iframe( { function preventFileDropDefault( event ) { event.preventDefault(); } + + const { ownerDocument } = node; + + // Ideally ALL classes that are added through get_body_class should + // be added in the editor too, which we'll somehow have to get from + // the server in the future (which will run the PHP filters). + setBodyClasses( + Array.from( ownerDocument.body.classList ).filter( + ( name ) => + name.startsWith( 'admin-color-' ) || + name.startsWith( 'post-type-' ) || + name === 'wp-embed-responsive' + ) + ); + function onLoad() { - const { contentDocument, ownerDocument } = node; + const { contentDocument } = node; const { documentElement } = contentDocument; iFrameDocument = contentDocument; @@ -140,18 +155,6 @@ function Iframe( { clearerRef( documentElement ); - // Ideally ALL classes that are added through get_body_class should - // be added in the editor too, which we'll somehow have to get from - // the server in the future (which will run the PHP filters). - setBodyClasses( - Array.from( ownerDocument.body.classList ).filter( - ( name ) => - name.startsWith( 'admin-color-' ) || - name.startsWith( 'post-type-' ) || - name === 'wp-embed-responsive' - ) - ); - contentDocument.dir = ownerDocument.dir; for ( const compatStyle of getCompatibilityStyles() ) { diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index 20aa1c288103d4..9051441af2cef6 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -644,5 +644,10 @@ $block-inserter-tabs-height: 44px; } .block-editor-tabbed-sidebar__tabpanel .block-editor-inserter__help-text { + display: none; padding: 0 $grid-unit-30 $grid-unit-20; + + @include break-mobile { + display: block; + } } diff --git a/packages/block-library/src/cover/edit/index.js b/packages/block-library/src/cover/edit/index.js index 1eafe99e283eb4..b09093e312211d 100644 --- a/packages/block-library/src/cover/edit/index.js +++ b/packages/block-library/src/cover/edit/index.js @@ -514,6 +514,8 @@ function CoverEdit( { value={ overlayColor.color } onChange={ onSetOverlayColor } clearable={ false } + asButtons + aria-label={ __( 'Overlay color' ) } />
diff --git a/packages/block-library/src/cover/test/edit.js b/packages/block-library/src/cover/test/edit.js index 0a18d2cf3f9f8e..16695f53f67466 100644 --- a/packages/block-library/src/cover/test/edit.js +++ b/packages/block-library/src/cover/test/edit.js @@ -47,7 +47,7 @@ async function setup( attributes, useCoreBlocks, customSettings ) { async function createAndSelectBlock() { await userEvent.click( - screen.getByRole( 'option', { + screen.getByRole( 'button', { name: 'Black', } ) ); @@ -72,7 +72,7 @@ describe( 'Cover block', () => { test( 'can set overlay color using color picker on block placeholder', async () => { const { container } = await setup(); - const colorPicker = screen.getByRole( 'option', { + const colorPicker = screen.getByRole( 'button', { name: 'Black', } ); await userEvent.click( colorPicker ); @@ -96,7 +96,7 @@ describe( 'Cover block', () => { await setup(); await userEvent.click( - screen.getByRole( 'option', { + screen.getByRole( 'button', { name: 'Black', } ) ); @@ -389,7 +389,7 @@ describe( 'Cover block', () => { describe( 'isDark settings', () => { test( 'should toggle is-light class if background changed from light to dark', async () => { await setup(); - const colorPicker = screen.getByRole( 'option', { + const colorPicker = screen.getByRole( 'button', { name: 'White', } ); await userEvent.click( colorPicker ); @@ -413,7 +413,7 @@ describe( 'Cover block', () => { } ); test( 'should remove is-light class if overlay color is removed', async () => { await setup(); - const colorPicker = screen.getByRole( 'option', { + const colorPicker = screen.getByRole( 'button', { name: 'White', } ); await userEvent.click( colorPicker ); @@ -426,7 +426,7 @@ describe( 'Cover block', () => { } ) ); await userEvent.click( screen.getByText( 'Overlay' ) ); - // The default color is black, so clicking the black color option will remove the background color, + // The default color is black, so clicking the black color button will remove the background color, // which should remove the isDark setting and assign the is-light class. const popupColorPicker = screen.getByRole( 'option', { name: 'White', diff --git a/packages/block-library/src/navigation-link/editor.scss b/packages/block-library/src/navigation-link/editor.scss index b27c4520921fd4..5034c6f909ecdc 100644 --- a/packages/block-library/src/navigation-link/editor.scss +++ b/packages/block-library/src/navigation-link/editor.scss @@ -82,30 +82,9 @@ // Draw a wavy underline. .wp-block-navigation-link__placeholder-text { span { - $blur: 10%; - $width: 6%; - $stop1: 30%; - $stop2: 64%; - - --wp-underline-color: var(--wp-admin-theme-color); - - background-image: - linear-gradient(45deg, transparent ($stop1 - $blur), var(--wp-underline-color) $stop1, var(--wp-underline-color) ($stop1 + $width), transparent ($stop1 + $width + $blur)), - linear-gradient(135deg, transparent ($stop2 - $blur), var(--wp-underline-color) $stop2, var(--wp-underline-color) ($stop2 + $width), transparent ($stop2 + $width + $blur)); - background-position: 0 100%; - background-size: 6px 3px; - background-repeat: repeat-x; - - // Since applied to a span, it doesn't change the footprint of the item, - // but it does vertically shift the underline to better align. - padding-bottom: 0.1em; - } - - &.is-invalid, - &.is-draft { - span { - --wp-underline-color: #{$alert-red}; - } + text-decoration: wavy underline; + text-decoration-skip-ink: none; + text-underline-offset: 0.25rem; } } diff --git a/packages/block-library/src/query-total/index.php b/packages/block-library/src/query-total/index.php index ff2ac486727b92..ba99b324601331 100644 --- a/packages/block-library/src/query-total/index.php +++ b/packages/block-library/src/query-total/index.php @@ -10,6 +10,8 @@ * * @since 6.8.0 * + * @global WP_Query $wp_query WordPress Query object. + * * @param array $attributes Block attributes. * @param string $content Block default content. * @param WP_Block $block Block instance. diff --git a/packages/components/src/border-box-control/test/index.tsx b/packages/components/src/border-box-control/test/index.tsx index fb536656453f4d..74501f7fccc7ac 100644 --- a/packages/components/src/border-box-control/test/index.tsx +++ b/packages/components/src/border-box-control/test/index.tsx @@ -202,7 +202,7 @@ describe( 'BorderBoxControl', () => { await waitFor( () => expect( screen.getByRole( 'button', { - name: 'Custom color picker.', + name: 'Custom color picker', } ) ).toBeVisible() ); diff --git a/packages/components/src/border-control/test/index.js b/packages/components/src/border-control/test/index.js index ff9007be28f1a2..c3e3987ed13517 100644 --- a/packages/components/src/border-control/test/index.js +++ b/packages/components/src/border-control/test/index.js @@ -138,7 +138,7 @@ describe( 'BorderControl', () => { const customColorPicker = getButton( /Custom color picker/ ); const circularOptionPicker = screen.getByRole( 'listbox', { - name: 'Custom color picker.', + name: 'Custom color picker', } ); const colorSwatchButtons = within( circularOptionPicker ).getAllByRole( 'option' ); diff --git a/packages/components/src/circular-option-picker/README.md b/packages/components/src/circular-option-picker/README.md index b6db6f06daf456..8a4d5ac3cf5ca3 100644 --- a/packages/components/src/circular-option-picker/README.md +++ b/packages/components/src/circular-option-picker/README.md @@ -93,6 +93,19 @@ Prevents keyboard interaction from wrapping around. Only used when `asButtons` i - Required: No - Default: `true` +### `aria-labelledby`: `string` + +The ID reference list of one or more elements that label the wrapper element. + +- Required: No + +### `aria-label`: `string` + +The label for the wrapper element. Not used if an 'aria-labelledby' is provided. + +- Required: No +- Default: `Custom color picker` + ## Subcomponents ### `CircularOptionPicker.ButtonAction` diff --git a/packages/components/src/circular-option-picker/circular-option-picker.tsx b/packages/components/src/circular-option-picker/circular-option-picker.tsx index 8b6be8cd2215f0..c4309ecf4dda3d 100644 --- a/packages/components/src/circular-option-picker/circular-option-picker.tsx +++ b/packages/components/src/circular-option-picker/circular-option-picker.tsx @@ -132,7 +132,7 @@ function ButtonsCircularOptionPicker( ); return ( -
+
{ options } { children } diff --git a/packages/components/src/circular-option-picker/index.tsx b/packages/components/src/circular-option-picker/index.tsx index ef975c21ee6545..ef379994b476f5 100644 --- a/packages/components/src/circular-option-picker/index.tsx +++ b/packages/components/src/circular-option-picker/index.tsx @@ -9,5 +9,6 @@ export { ButtonAction, DropdownLinkAction, } from './circular-option-picker-actions'; +export { getComputeCircularOptionPickerCommonProps } from './utils'; export default CircularOptionPicker; diff --git a/packages/components/src/circular-option-picker/stories/index.story.tsx b/packages/components/src/circular-option-picker/stories/index.story.tsx index 9d45c9bb92f7d0..6b564929fd8eb9 100644 --- a/packages/components/src/circular-option-picker/stories/index.story.tsx +++ b/packages/components/src/circular-option-picker/stories/index.story.tsx @@ -131,7 +131,7 @@ WithLoopingDisabled.parameters = { docs: { source: { code: `} />`, diff --git a/packages/components/src/circular-option-picker/test/index.tsx b/packages/components/src/circular-option-picker/test/index.tsx index a6e9f2c45a05ce..7d58ed3920f9bd 100644 --- a/packages/components/src/circular-option-picker/test/index.tsx +++ b/packages/components/src/circular-option-picker/test/index.tsx @@ -57,6 +57,7 @@ describe( 'CircularOptionPicker', () => { expect( screen.queryByRole( 'listbox' ) ).not.toBeInTheDocument(); expect( screen.queryByRole( 'option' ) ).not.toBeInTheDocument(); + expect( screen.getByRole( 'group' ) ).toBeInTheDocument(); expect( screen.getByRole( 'button' ) ).toBeInTheDocument(); } ); } ); diff --git a/packages/components/src/circular-option-picker/types.ts b/packages/components/src/circular-option-picker/types.ts index 411782aed575b1..54fae3ab2e798a 100644 --- a/packages/components/src/circular-option-picker/types.ts +++ b/packages/components/src/circular-option-picker/types.ts @@ -40,6 +40,16 @@ type CommonCircularOptionPickerProps = { * The child elements. */ children?: ReactNode; + /** + * The ID reference list of one or more elements that label the wrapper + * element. + */ + 'aria-labelledby'?: string; + /** + * The label for the wrapper element. Defaults to 'Custom color picker'. Not + * used if an 'aria-labelledby' is provided. + */ + 'aria-label'?: string; }; type WithBaseId = { @@ -59,16 +69,7 @@ type FullListboxCircularOptionPickerProps = CommonCircularOptionPickerProps & { * @default true */ loop?: boolean; -} & ( - | { - 'aria-label': string; - 'aria-labelledby'?: never; - } - | { - 'aria-label'?: never; - 'aria-labelledby': string; - } - ); +}; export type ListboxCircularOptionPickerProps = WithBaseId & Omit< FullListboxCircularOptionPickerProps, 'asButtons' >; diff --git a/packages/components/src/circular-option-picker/utils.tsx b/packages/components/src/circular-option-picker/utils.tsx new file mode 100644 index 00000000000000..fcb3b2bcac3695 --- /dev/null +++ b/packages/components/src/circular-option-picker/utils.tsx @@ -0,0 +1,27 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Computes the common props for the CircularOptionPicker. + */ +export function getComputeCircularOptionPickerCommonProps( + asButtons?: boolean, + loop?: boolean, + ariaLabel?: string, + ariaLabelledby?: string +) { + const metaProps = asButtons + ? { asButtons: true } + : { asButtons: false, loop }; + + const labelProps = { + 'aria-labelledby': ariaLabelledby, + 'aria-label': ariaLabelledby + ? undefined + : ariaLabel || __( 'Custom color picker' ), + }; + + return { metaProps, labelProps }; +} diff --git a/packages/components/src/color-palette/index.tsx b/packages/components/src/color-palette/index.tsx index de4e4f4206fe3a..eb981e8b9acc70 100644 --- a/packages/components/src/color-palette/index.tsx +++ b/packages/components/src/color-palette/index.tsx @@ -19,7 +19,9 @@ import { useCallback, useMemo, useState, forwardRef } from '@wordpress/element'; */ import Dropdown from '../dropdown'; import { ColorPicker } from '../color-picker'; -import CircularOptionPicker from '../circular-option-picker'; +import CircularOptionPicker, { + getComputeCircularOptionPickerCommonProps, +} from '../circular-option-picker'; import { VStack } from '../v-stack'; import { Truncate } from '../truncate'; import { ColorHeading } from './styles'; @@ -233,7 +235,7 @@ function UnforwardedColorPalette( buttonLabelName, displayValue ) - : __( 'Custom color picker.' ); + : __( 'Custom color picker' ); const paletteCommonProps = { clearColor, @@ -251,33 +253,12 @@ function UnforwardedColorPalette( ); - let metaProps: - | { asButtons: false; loop?: boolean; 'aria-label': string } - | { asButtons: false; loop?: boolean; 'aria-labelledby': string } - | { asButtons: true }; - - if ( asButtons ) { - metaProps = { asButtons: true }; - } else { - const _metaProps: { asButtons: false; loop?: boolean } = { - asButtons: false, - loop, - }; - - if ( ariaLabel ) { - metaProps = { ..._metaProps, 'aria-label': ariaLabel }; - } else if ( ariaLabelledby ) { - metaProps = { - ..._metaProps, - 'aria-labelledby': ariaLabelledby, - }; - } else { - metaProps = { - ..._metaProps, - 'aria-label': __( 'Custom color picker.' ), - }; - } - } + const { metaProps, labelProps } = getComputeCircularOptionPickerCommonProps( + asButtons, + loop, + ariaLabel, + ariaLabelledby + ); return ( @@ -335,6 +316,7 @@ function UnforwardedColorPalette( { ( colors.length > 0 || actions ) && ( { expect( screen.queryByText( colorCode ) ).not.toBeInTheDocument(); expect( screen.getByRole( 'button', { - name: /^Custom color picker.$/, + name: /^Custom color picker$/, } ) ).toBeInTheDocument(); } ); diff --git a/packages/components/src/duotone-picker/duotone-picker.tsx b/packages/components/src/duotone-picker/duotone-picker.tsx index 8764b401c38296..a21d12b73a65c4 100644 --- a/packages/components/src/duotone-picker/duotone-picker.tsx +++ b/packages/components/src/duotone-picker/duotone-picker.tsx @@ -13,7 +13,9 @@ import { __, sprintf } from '@wordpress/i18n'; * Internal dependencies */ import ColorListPicker from './color-list-picker'; -import CircularOptionPicker from '../circular-option-picker'; +import CircularOptionPicker, { + getComputeCircularOptionPickerCommonProps, +} from '../circular-option-picker'; import { VStack } from '../v-stack'; import CustomDuotoneBar from './custom-duotone-bar'; @@ -127,33 +129,12 @@ function DuotonePicker( { ); } ); - let metaProps: - | { asButtons: false; loop?: boolean; 'aria-label': string } - | { asButtons: false; loop?: boolean; 'aria-labelledby': string } - | { asButtons: true }; - - if ( asButtons ) { - metaProps = { asButtons: true }; - } else { - const _metaProps: { asButtons: false; loop?: boolean } = { - asButtons: false, - loop, - }; - - if ( ariaLabel ) { - metaProps = { ..._metaProps, 'aria-label': ariaLabel }; - } else if ( ariaLabelledby ) { - metaProps = { - ..._metaProps, - 'aria-labelledby': ariaLabelledby, - }; - } else { - metaProps = { - ..._metaProps, - 'aria-label': __( 'Custom color picker.' ), - }; - } - } + const { metaProps, labelProps } = getComputeCircularOptionPickerCommonProps( + asButtons, + loop, + ariaLabel, + ariaLabelledby + ); const options = unsetable ? [ unsetOption, ...duotoneOptions ] @@ -163,6 +144,7 @@ function DuotonePicker( { ) { ); - let metaProps: - | { asButtons: false; loop?: boolean; 'aria-label': string } - | { asButtons: false; loop?: boolean; 'aria-labelledby': string } - | { asButtons: true }; - - if ( asButtons ) { - metaProps = { asButtons: true }; - } else { - const _metaProps: { asButtons: false; loop?: boolean } = { - asButtons: false, - loop, - }; - - if ( ariaLabel ) { - metaProps = { ..._metaProps, 'aria-label': ariaLabel }; - } else if ( ariaLabelledby ) { - metaProps = { - ..._metaProps, - 'aria-labelledby': ariaLabelledby, - }; - } else { - metaProps = { - ..._metaProps, - 'aria-label': __( 'Custom color picker.' ), - }; - } - } + const { metaProps, labelProps } = getComputeCircularOptionPickerCommonProps( + asButtons, + loop, + ariaLabel, + ariaLabelledby + ); return ( diff --git a/packages/edit-site/src/components/site-editor-routes/patterns.js b/packages/edit-site/src/components/site-editor-routes/patterns.js index db97c4b5c080fd..785528f09afb04 100644 --- a/packages/edit-site/src/components/site-editor-routes/patterns.js +++ b/packages/edit-site/src/components/site-editor-routes/patterns.js @@ -1,8 +1,27 @@ +/** + * WordPress dependencies + */ +import { privateApis as routerPrivateApis } from '@wordpress/router'; + /** * Internal dependencies */ import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns'; import PagePatterns from '../page-patterns'; +import { unlock } from '../../lock-unlock'; + +const { useLocation } = unlock( routerPrivateApis ); + +function MobilePatternsView() { + const { query = {} } = useLocation(); + const { categoryId } = query; + + return !! categoryId ? ( + + ) : ( + + ); +} export const patternsRoute = { name: 'patterns', @@ -10,6 +29,6 @@ export const patternsRoute = { areas: { sidebar: , content: , - mobile: , + mobile: , }, }; diff --git a/test/e2e/specs/editor/blocks/buttons.spec.js b/test/e2e/specs/editor/blocks/buttons.spec.js index 554bd8947f0bf5..7830a934529aa4 100644 --- a/test/e2e/specs/editor/blocks/buttons.spec.js +++ b/test/e2e/specs/editor/blocks/buttons.spec.js @@ -324,13 +324,13 @@ test.describe( 'Buttons', () => { await page.click( 'role=region[name="Editor settings"i] >> role=button[name="Text"i]' ); - await page.click( 'role=button[name="Custom color picker."i]' ); + await page.click( 'role=button[name="Custom color picker"i]' ); await page.fill( 'role=textbox[name="Hex color"i]', 'ff0000' ); await page.click( 'role=region[name="Editor settings"i] >> role=button[name="Background"i]' ); - await page.click( 'role=button[name="Custom color picker."i]' ); + await page.click( 'role=button[name="Custom color picker"i]' ); await page.fill( 'role=textbox[name="Hex color"i]', '00ff00' ); // Check the content. diff --git a/test/e2e/specs/editor/blocks/cover.spec.js b/test/e2e/specs/editor/blocks/cover.spec.js index 87c244a7306dc6..bee2548c2305d2 100644 --- a/test/e2e/specs/editor/blocks/cover.spec.js +++ b/test/e2e/specs/editor/blocks/cover.spec.js @@ -33,7 +33,7 @@ test.describe( 'Cover', () => { } ); // Locate the Black color swatch. - const blackColorSwatch = coverBlock.getByRole( 'option', { + const blackColorSwatch = coverBlock.getByRole( 'button', { name: 'Black', } ); await expect( blackColorSwatch ).toBeVisible(); @@ -105,7 +105,7 @@ test.describe( 'Cover', () => { // Choose a color swatch to transform the placeholder block into // a functioning block. await coverBlock - .getByRole( 'option', { + .getByRole( 'button', { name: 'Black', } ) .click(); @@ -128,7 +128,7 @@ test.describe( 'Cover', () => { name: 'Block: Cover', } ); await coverBlock - .getByRole( 'option', { + .getByRole( 'button', { name: 'Black', } ) .click(); @@ -240,7 +240,7 @@ test.describe( 'Cover', () => { // Choose a color swatch to transform the placeholder block into // a functioning block. await coverBlock - .getByRole( 'option', { + .getByRole( 'button', { name: 'Black', } ) .click(); @@ -266,7 +266,7 @@ test.describe( 'Cover', () => { // Choose a color swatch to transform the placeholder block into // a functioning block. await secondCoverBlock - .getByRole( 'option', { + .getByRole( 'button', { name: 'Black', } ) .click(); diff --git a/test/e2e/specs/editor/blocks/heading.spec.js b/test/e2e/specs/editor/blocks/heading.spec.js index 906095cad9d080..6ff7e11bb334e0 100644 --- a/test/e2e/specs/editor/blocks/heading.spec.js +++ b/test/e2e/specs/editor/blocks/heading.spec.js @@ -184,7 +184,7 @@ test.describe( 'Heading', () => { await textColor.click(); await page - .getByRole( 'button', { name: /Custom color picker./i } ) + .getByRole( 'button', { name: /Custom color picker/i } ) .click(); await page diff --git a/test/e2e/specs/editor/various/block-editor-dark-background.spec.js b/test/e2e/specs/editor/various/block-editor-dark-background.spec.js new file mode 100644 index 00000000000000..dc333f31c7ed9d --- /dev/null +++ b/test/e2e/specs/editor/various/block-editor-dark-background.spec.js @@ -0,0 +1,52 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Block editor with dark background theme', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'darktheme' ); + } ); + + test.beforeEach( async ( { admin } ) => { + await admin.createNewPost(); + } ); + + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyone' ); + } ); + + test.describe( 'Block editor iframe body', () => { + test( 'Should have the is-dark-theme CSS class', async ( { + editor, + } ) => { + const canvasBody = editor.canvas.locator( 'body' ); + + await expect( canvasBody ).toHaveClass( /is-dark-theme/ ); + } ); + } ); +} ); + +test.describe( 'Block editor with light background theme', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyfour' ); + } ); + + test.beforeEach( async ( { admin } ) => { + await admin.createNewPost(); + } ); + + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyone' ); + } ); + + test.describe( 'Block editor iframe body', () => { + test( 'Should not have the is-dark-theme CSS class', async ( { + editor, + } ) => { + const canvasBody = editor.canvas.locator( 'body' ); + + await expect( canvasBody ).not.toHaveClass( /is-dark-theme/ ); + } ); + } ); +} ); diff --git a/test/e2e/specs/editor/various/list-view.spec.js b/test/e2e/specs/editor/various/list-view.spec.js index 988683c8d11aa3..98dfe5e304f802 100644 --- a/test/e2e/specs/editor/various/list-view.spec.js +++ b/test/e2e/specs/editor/various/list-view.spec.js @@ -162,10 +162,10 @@ test.describe( 'List View', () => { // make the inner blocks appear. await editor.canvas .getByRole( 'document', { name: 'Block: Cover' } ) - .getByRole( 'listbox', { - name: 'Custom color picker.', + .getByRole( 'group', { + name: 'Overlay color', } ) - .getByRole( 'option' ) + .getByRole( 'button' ) .first() .click(); diff --git a/test/e2e/specs/site-editor/preload.spec.js b/test/e2e/specs/site-editor/preload.spec.js index b6f9f49aedeb7c..e618d70ca20b90 100644 --- a/test/e2e/specs/site-editor/preload.spec.js +++ b/test/e2e/specs/site-editor/preload.spec.js @@ -46,9 +46,6 @@ test.describe( 'Preload', () => { expect( requests ).toEqual( [ // Seems to be coming from `enableComplementaryArea`. '/wp/v2/users/me', - // There are two separate settings OPTIONS requests. We should fix - // so the one for canUser and getEntityRecord are reused. - '/wp/v2/settings', ] ); } ); } ); diff --git a/test/e2e/specs/site-editor/site-editor-dark-background.spec.js b/test/e2e/specs/site-editor/site-editor-dark-background.spec.js new file mode 100644 index 00000000000000..1bf49c196bdfc6 --- /dev/null +++ b/test/e2e/specs/site-editor/site-editor-dark-background.spec.js @@ -0,0 +1,75 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Site editor with dark background theme', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'darktheme' ); + } ); + + test.beforeEach( async ( { admin } ) => { + await admin.visitSiteEditor(); + } ); + + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyone' ); + } ); + + test.describe( 'Site editor iframe body', () => { + test( 'Should have the is-dark-theme CSS class', async ( { + editor, + } ) => { + const canvasBody = editor.canvas.locator( 'body' ); + + await expect( canvasBody ).toHaveClass( /is-dark-theme/ ); + } ); + } ); +} ); + +test.describe( 'Site editor with light background theme and theme variations', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyfour' ); + } ); + + test.beforeEach( async ( { admin } ) => { + await admin.visitSiteEditor(); + } ); + + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyone' ); + } ); + + test.describe( 'Site editor iframe body', () => { + test( 'Should not have the is-dark-theme CSS class', async ( { + editor, + } ) => { + const canvasBody = editor.canvas.locator( 'body' ); + + await expect( canvasBody ).not.toHaveClass( /is-dark-theme/ ); + } ); + + test( 'Should add and remove the is-dark-theme CSS class with dark and light theme variation', async ( { + page, + editor, + } ) => { + // Click "Styles" + await page.getByRole( 'button', { name: 'Styles' } ).click(); + + // Click "Browse styles" + await page.getByRole( 'button', { name: 'Browse styles' } ).click(); + + const canvasBody = editor.canvas.locator( 'body' ); + + // Activate "Maelstrom" Theme Variation. + await page.getByRole( 'button', { name: 'Maelstrom' } ).click(); + + await expect( canvasBody ).toHaveClass( /is-dark-theme/ ); + + // Activate "Ember" Theme Variation. + await page.getByRole( 'button', { name: 'Ember' } ).click(); + + await expect( canvasBody ).not.toHaveClass( /is-dark-theme/ ); + } ); + } ); +} ); diff --git a/test/gutenberg-test-themes/darktheme/block-templates/index.html b/test/gutenberg-test-themes/darktheme/block-templates/index.html new file mode 100644 index 00000000000000..0283daeb54c6f4 --- /dev/null +++ b/test/gutenberg-test-themes/darktheme/block-templates/index.html @@ -0,0 +1,11 @@ + +
+ + + + +
+ + +

My awesome paragraph

+ diff --git a/test/gutenberg-test-themes/darktheme/block-templates/singular.html b/test/gutenberg-test-themes/darktheme/block-templates/singular.html new file mode 100644 index 00000000000000..cd05d5fe917fea --- /dev/null +++ b/test/gutenberg-test-themes/darktheme/block-templates/singular.html @@ -0,0 +1,2 @@ + + diff --git a/test/gutenberg-test-themes/darktheme/index.php b/test/gutenberg-test-themes/darktheme/index.php new file mode 100644 index 00000000000000..0c6530acc1aaff --- /dev/null +++ b/test/gutenberg-test-themes/darktheme/index.php @@ -0,0 +1,9 @@ +