From 4011f4b179d8e67dcf0d422b01af9139ab48795c Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Mon, 17 Jun 2024 15:25:12 +1000 Subject: [PATCH] Improve maintainability of theme json class tests. (#62463) Co-authored-by: tellthemachines Co-authored-by: aaronrobertshaw Co-authored-by: andrewserong --- phpunit/bootstrap.php | 85 ------ phpunit/class-wp-theme-json-test.php | 371 +++++++++------------------ 2 files changed, 120 insertions(+), 336 deletions(-) diff --git a/phpunit/bootstrap.php b/phpunit/bootstrap.php index acc7cfde89dbd4..295d02978f120f 100644 --- a/phpunit/bootstrap.php +++ b/phpunit/bootstrap.php @@ -101,91 +101,6 @@ function fail_if_died( $message ) { // Enable the widget block editor. tests_add_filter( 'gutenberg_use_widgets_block_editor', '__return_true' ); -/** - * Register test block prior to theme.json generating metadata. - * - * This new block is used to test experimental selectors. It is registered - * via `tests_add_filter()` here during bootstrapping so that it occurs prior - * to theme.json generating block metadata. Once a core block, such as Image, - * uses feature level selectors we could remove this in favour of testing via - * the core block. - */ -function gutenberg_register_test_block_for_feature_selectors() { - WP_Block_Type_Registry::get_instance()->register( - 'test/test', - array( - 'api_version' => 3, - 'attributes' => array( - 'textColor' => array( - 'type' => 'string', - ), - 'style' => array( - 'type' => 'object', - ), - ), - 'supports' => array( - '__experimentalBorder' => array( - 'radius' => true, - '__experimentalSelector' => '.inner', - ), - 'color' => array( - 'text' => true, - ), - 'spacing' => array( - 'padding' => true, - '__experimentalSelector' => '.inner', - ), - 'typography' => array( - 'fontSize' => true, - '__experimentalSelector' => '.sub-heading', - ), - '__experimentalSelector' => '.wp-block-test, .wp-block-test__wrapper', - ), - ) - ); - - WP_Block_Type_Registry::get_instance()->register( - 'my/block-with-selectors', - array( - 'api_version' => 2, - 'attributes' => array( - 'textColor' => array( - 'type' => 'string', - ), - 'style' => array( - 'type' => 'object', - ), - ), - 'supports' => array( - '__experimentalBorder' => array( - 'radius' => true, - ), - 'color' => array( - 'background' => true, - 'text' => true, - ), - 'spacing' => array( - 'padding' => true, - ), - 'typography' => array( - 'fontSize' => true, - ), - ), - 'selectors' => array( - 'root' => '.custom-root-selector', - 'border' => array( - 'root' => '.custom-root-selector img', - ), - 'color' => array( - 'text' => '.custom-root-selector > figcaption', - ), - 'typography' => '.custom-root-selector > figcaption', - ), - ) - ); -} -tests_add_filter( 'init', 'gutenberg_register_test_block_for_feature_selectors' ); - // Start up the WP testing environment. require $_tests_dir . '/includes/bootstrap.php'; diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 59dcf07c040b52..cb4d5458111c66 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -562,7 +562,7 @@ public function test_get_stylesheet() { $this->assertSame( $all, $theme_json->get_stylesheet() ); } - public function test_get_stylesheet_support_for_shorthand_and_longhand_values() { + public function test_get_styles_for_block_support_for_shorthand_and_longhand_values() { $theme_json = new WP_Theme_JSON_Gutenberg( array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, @@ -598,9 +598,28 @@ public function test_get_stylesheet_support_for_shorthand_and_longhand_values() ) ); - $styles = static::$base_styles . ':root :where(.wp-block-group){border-radius: 10px;margin: 1em;padding: 24px;}:root :where(.wp-block-image){margin-bottom: 30px;padding-top: 15px;}:root :where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-top-left-radius: 10px;border-bottom-right-radius: 1em;}'; - $this->assertSame( $styles, $theme_json->get_stylesheet() ); - $this->assertSame( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $group_node = array( + 'name' => 'core/group', + 'path' => array( 'styles', 'blocks', 'core/group' ), + 'selector' => '.wp-block-group', + 'selectors' => array( + 'root' => '.wp-block-group', + ), + ); + $image_node = array( + 'name' => 'core/image', + 'path' => array( 'styles', 'blocks', 'core/image' ), + 'selector' => '.wp-block-image', + 'selectors' => array( + 'root' => '.wp-block-image', + 'border' => '.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder', + ), + ); + + $group_styles = ':root :where(.wp-block-group){border-radius: 10px;margin: 1em;padding: 24px;}'; + $image_styles = ':root :where(.wp-block-image){margin-bottom: 30px;padding-top: 15px;}:root :where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-top-left-radius: 10px;border-bottom-right-radius: 1em;}'; + $this->assertSame( $group_styles, $theme_json->get_styles_for_block( $group_node ) ); + $this->assertSame( $image_styles, $theme_json->get_styles_for_block( $image_node ) ); } public function test_get_stylesheet_skips_disabled_protected_properties() { @@ -711,14 +730,14 @@ public function test_get_stylesheet_preset_rules_come_after_block_rules() { ) ); - $styles = static::$base_styles . ':root :where(.wp-block-group){color: red;}'; + $styles = ':root :where(.wp-block-group){color: red;}'; $presets = '.wp-block-group.has-grey-color{color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}'; $variables = '.wp-block-group{--wp--preset--color--grey: grey;}'; $all = $variables . $styles . $presets; - $this->assertSame( $all, $theme_json->get_stylesheet() ); - $this->assertSame( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $this->assertSame( $all, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); + $this->assertSame( $styles, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); $this->assertSame( $presets, $theme_json->get_stylesheet( array( 'presets' ) ) ); $this->assertSame( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) ); } @@ -765,45 +784,7 @@ public function test_get_stylesheet_generates_proper_classes_and_css_vars_from_s ); } - public function test_get_stylesheet_preset_values_are_marked_as_important() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'grey', - 'color' => 'grey', - ), - ), - ), - ), - 'styles' => array( - 'blocks' => array( - 'core/paragraph' => array( - 'color' => array( - 'text' => 'red', - 'background' => 'blue', - ), - 'typography' => array( - 'fontSize' => '12px', - 'lineHeight' => '1.3', - ), - ), - ), - ), - ), - 'default' - ); - - $this->assertSame( - ':root{--wp--preset--color--grey: grey;}' . static::$base_styles . ':root :where(p){background-color: blue;color: red;font-size: 12px;line-height: 1.3;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}', - $theme_json->get_stylesheet() - ); - } - - public function test_get_stylesheet_handles_whitelisted_element_pseudo_selectors() { + public function test_get_styles_for_block_handles_whitelisted_element_pseudo_selectors() { $theme_json = new WP_Theme_JSON_Gutenberg( array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, @@ -836,14 +817,31 @@ public function test_get_stylesheet_handles_whitelisted_element_pseudo_selectors ) ); - $element_styles = ':root :where(a:where(:not(.wp-element-button))){background-color: red;color: green;}:root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:root :where(a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; + $link_node = array( + 'path' => array( 'styles', 'elements', 'link' ), + 'selector' => 'a:where(:not(.wp-element-button))', + ); + $hover_node = array( + 'path' => array( 'styles', 'elements', 'link' ), + 'selector' => 'a:where(:not(.wp-element-button)):hover', + ); + $focus_node = array( + 'path' => array( 'styles', 'elements', 'link' ), + 'selector' => 'a:where(:not(.wp-element-button)):focus', + ); - $expected = static::$base_styles . $element_styles; + $link_style = ':root :where(a:where(:not(.wp-element-button))){background-color: red;color: green;}'; + $hover_style = ':root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}'; + $focus_style = ':root :where(a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $this->assertSame( $link_style, $theme_json->get_styles_for_block( $link_node ) ); + $this->assertSame( $hover_style, $theme_json->get_styles_for_block( $hover_node ) ); + $this->assertSame( $focus_style, $theme_json->get_styles_for_block( $focus_node ) ); } + /** + * Tests that if an element has nothing but pseudo selector styles, they are still output by get_stylesheet. + */ public function test_get_stylesheet_handles_only_pseudo_selector_rules_for_given_property() { $theme_json = new WP_Theme_JSON_Gutenberg( array( @@ -873,12 +871,9 @@ public function test_get_stylesheet_handles_only_pseudo_selector_rules_for_given ) ); - $element_styles = ':root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:root :where(a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; - - $expected = static::$base_styles . $element_styles; + $expected = ':root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:root :where(a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_stylesheet_ignores_pseudo_selectors_on_non_whitelisted_elements() { @@ -910,12 +905,9 @@ public function test_get_stylesheet_ignores_pseudo_selectors_on_non_whitelisted_ ) ); - $element_styles = ':root :where(h4){background-color: red;color: green;}'; - - $expected = static::$base_styles . $element_styles; + $expected = ':root :where(h4){background-color: red;color: green;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_stylesheet_ignores_non_whitelisted_pseudo_selectors() { @@ -947,15 +939,16 @@ public function test_get_stylesheet_ignores_non_whitelisted_pseudo_selectors() { ) ); - $element_styles = ':root :where(a:where(:not(.wp-element-button))){background-color: red;color: green;}:root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;}'; - - $expected = static::$base_styles . $element_styles; + $expected = ':root :where(a:where(:not(.wp-element-button))){background-color: red;color: green;}:root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); $this->assertStringNotContainsString( 'a:levitate{', $theme_json->get_stylesheet( array( 'styles' ) ) ); } + /** + * Tests that element pseudo selectors are output before block element pseudo selectors, and that whitelisted + * block element pseudo selectors are output correctly. + */ public function test_get_stylesheet_handles_priority_of_elements_vs_block_elements_pseudo_selectors() { $theme_json = new WP_Theme_JSON_Gutenberg( array( @@ -993,75 +986,20 @@ public function test_get_stylesheet_handles_priority_of_elements_vs_block_elemen ) ); - $element_styles = ':root :where(.wp-block-group a:where(:not(.wp-element-button))){background-color: red;color: green;}:root :where(.wp-block-group a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:root :where(.wp-block-group a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; - - $expected = static::$base_styles . $element_styles; + $expected = ':root :where(.wp-block-group a:where(:not(.wp-element-button))){background-color: red;color: green;}:root :where(.wp-block-group a:where(:not(.wp-element-button)):hover){background-color: green;color: red;font-size: 10em;text-transform: uppercase;}:root :where(.wp-block-group a:where(:not(.wp-element-button)):focus){background-color: black;color: yellow;}'; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); - } - - public function test_get_stylesheet_handles_whitelisted_block_level_element_pseudo_selectors() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'styles' => array( - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => 'green', - 'background' => 'red', - ), - ':hover' => array( - 'color' => array( - 'text' => 'red', - 'background' => 'green', - ), - ), - ), - ), - 'blocks' => array( - 'core/group' => array( - 'elements' => array( - 'link' => array( - ':hover' => array( - 'color' => array( - 'text' => 'yellow', - 'background' => 'black', - ), - ), - ), - ), - ), - ), - ), - ) - ); - - $element_styles = ':root :where(a:where(:not(.wp-element-button))){background-color: red;color: green;}:root :where(a:where(:not(.wp-element-button)):hover){background-color: green;color: red;}:root :where(.wp-block-group a:where(:not(.wp-element-button)):hover){background-color: black;color: yellow;}'; - - $expected = static::$base_styles . $element_styles; - - $this->assertSame( $expected, $theme_json->get_stylesheet() ); - $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) ); + $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } /** - * This test relies on a block having already been registered prior to - * theme.json generating block metadata. Until a core block, such as Image, - * opts into feature level selectors, we need to register a test block. - * This is achieved via `tests_add_filter()` in Gutenberg's phpunit - * bootstrap. After a core block adopts feature level selectors we could - * remove that filter and instead use the core block for the following test. + * This test checks that feature selectors defined as `__experimentalSelector` inside + * the `supports` property are correctly output in the stylesheet. */ public function test_get_stylesheet_with_deprecated_feature_level_selectors() { $theme_json = new WP_Theme_JSON_Gutenberg( array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( - 'border' => array( - 'radius' => true, - ), 'color' => array( 'custom' => false, 'palette' => array( @@ -1071,25 +1009,16 @@ public function test_get_stylesheet_with_deprecated_feature_level_selectors() { ), ), ), - 'spacing' => array( - 'padding' => true, - ), 'typography' => array( 'fontSize' => true, ), ), 'styles' => array( 'blocks' => array( - 'test/test' => array( - 'border' => array( - 'radius' => '9999px', - ), + 'core/calendar' => array( 'color' => array( 'text' => 'green', ), - 'spacing' => array( - 'padding' => '20px', - ), 'typography' => array( 'fontSize' => '3em', ), @@ -1099,61 +1028,33 @@ public function test_get_stylesheet_with_deprecated_feature_level_selectors() { ) ); - $base_styles = ':root{--wp--preset--color--green: green;}' . static::$base_styles; - $block_styles = ':root :where(.wp-block-test, .wp-block-test__wrapper){color: green;}:root :where(.wp-block-test .inner, .wp-block-test__wrapper .inner){border-radius: 9999px;padding: 20px;}:root :where(.wp-block-test .sub-heading, .wp-block-test__wrapper .sub-heading){font-size: 3em;}'; + $base_styles = ':root{--wp--preset--color--green: green;}'; + $block_styles = ':root :where(.wp-block-calendar){font-size: 3em;}:root :where(.wp-block-calendar table, .wp-block-calendar th){color: green;}'; $preset_styles = '.has-green-color{color: var(--wp--preset--color--green) !important;}.has-green-background-color{background-color: var(--wp--preset--color--green) !important;}.has-green-border-color{border-color: var(--wp--preset--color--green) !important;}'; $expected = $base_styles . $block_styles . $preset_styles; - $this->assertEquals( $expected, $theme_json->get_stylesheet() ); + $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); } + /** - * This test relies on a block having already been registered prior to - * theme.json generating block metadata. Until a core block adopts the - * new selectors API, we need to register a test block. - * This is achieved via `tests_add_filter()` in Gutenberg's phpunit - * bootstrap. After a core block adopts feature level selectors we could - * remove that filter and instead use the core block for the following test. + * This test checks that feature selectors defined in the stable `selectors` + * property are correctly output in the stylesheet. */ public function test_get_stylesheet_with_block_json_selectors() { $theme_json = new WP_Theme_JSON_Gutenberg( array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( - 'border' => array( + 'border' => array( 'radius' => true, ), - 'color' => array( - 'custom' => false, - 'palette' => array( - array( - 'slug' => 'green', - 'color' => 'green', - ), - ), - ), - 'spacing' => array( - 'padding' => true, - ), - 'typography' => array( - 'fontSize' => true, - ), ), 'styles' => array( 'blocks' => array( - 'my/block-with-selectors' => array( - 'border' => array( - 'radius' => '9999px', - ), - 'color' => array( - 'background' => 'grey', - 'text' => 'navy', - ), - 'spacing' => array( - 'padding' => '20px', - ), - 'typography' => array( - 'fontSize' => '3em', + 'core/image' => array( + 'border' => array( + 'radius' => '374px', ), ), ), @@ -1161,12 +1062,9 @@ public function test_get_stylesheet_with_block_json_selectors() { ) ); - $base_styles = ':root{--wp--preset--color--green: green;}' . static::$base_styles; - $block_styles = ':root :where(.custom-root-selector){background-color: grey;padding: 20px;}:root :where(.custom-root-selector img){border-radius: 9999px;}:root :where(.custom-root-selector > figcaption){color: navy;font-size: 3em;}'; - $preset_styles = '.has-green-color{color: var(--wp--preset--color--green) !important;}.has-green-background-color{background-color: var(--wp--preset--color--green) !important;}.has-green-border-color{border-color: var(--wp--preset--color--green) !important;}'; - $expected = $base_styles . $block_styles . $preset_styles; + $expected = ':root :where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-radius: 374px;}'; - $this->assertEquals( $expected, $theme_json->get_stylesheet() ); + $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_stylesheet_generates_layout_styles() { @@ -1262,10 +1160,6 @@ public function test_get_stylesheet_generates_base_fallback_gap_layout_styles() array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( - 'layout' => array( - 'contentSize' => '640px', - 'wideSize' => '1200px', - ), 'spacing' => array( 'blockGap' => null, ), @@ -1383,10 +1277,9 @@ public function test_get_stylesheet_returns_outline_styles() { ) ); - $element_styles = ':root :where(.wp-element-button, .wp-block-button__link){outline-color: red;outline-offset: 3px;outline-style: dashed;outline-width: 3px;}:root :where(.wp-element-button:hover, .wp-block-button__link:hover){outline-color: blue;outline-offset: 3px;outline-style: solid;outline-width: 3px;}'; + $expected = ':root :where(.wp-element-button, .wp-block-button__link){outline-color: red;outline-offset: 3px;outline-style: dashed;outline-width: 3px;}:root :where(.wp-element-button:hover, .wp-block-button__link:hover){outline-color: blue;outline-offset: 3px;outline-style: solid;outline-width: 3px;}'; - $expected = static::$base_styles . $element_styles; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); + $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_stylesheet_custom_root_selector() { @@ -1402,13 +1295,15 @@ public function test_get_stylesheet_custom_root_selector() { 'default' ); - $options = array( 'root_selector' => '.custom' ); + // Custom root selector is unrelated to root layout styles so they don't need to be output for this test. + $options = array( + 'root_selector' => '.custom', + 'skip_root_layout_styles' => true, + ); $actual = $theme_json->get_stylesheet( array( 'styles' ), null, $options ); - // Results also include root site blocks styles which hard code - // `:where(body) { margin: 0; }`. $this->assertSame( - ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:root :where(.custom){color: teal;}', + ':root :where(.custom){color: teal;}', $actual ); } @@ -1465,10 +1360,9 @@ public function test_get_stylesheet_generates_fluid_typography_values() { unregister_block_type( 'test/clamp-me' ); - // Results also include root site blocks styles. $this->assertSame( - ':root{--wp--preset--font-size--pickles: clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.156), 16px);--wp--preset--font-size--toast: clamp(14.642px, 0.915rem + ((1vw - 3.2px) * 0.575), 22px);}:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:root :where(body){font-size: clamp(0.875em, 0.875rem + ((1vw - 0.2em) * 0.156), 1em);}:root :where(h1){font-size: clamp(50.171px, 3.136rem + ((1vw - 3.2px) * 3.893), 100px);}:root :where(.wp-block-test-clamp-me){font-size: clamp(27.894px, 1.743rem + ((1vw - 3.2px) * 1.571), 48px);}.has-pickles-font-size{font-size: var(--wp--preset--font-size--pickles) !important;}.has-toast-font-size{font-size: var(--wp--preset--font-size--toast) !important;}', - $theme_json->get_stylesheet() + ':root{--wp--preset--font-size--pickles: clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.156), 16px);--wp--preset--font-size--toast: clamp(14.642px, 0.915rem + ((1vw - 3.2px) * 0.575), 22px);}:root :where(body){font-size: clamp(0.875em, 0.875rem + ((1vw - 0.2em) * 0.156), 1em);}:root :where(h1){font-size: clamp(50.171px, 3.136rem + ((1vw - 3.2px) * 3.893), 100px);}:root :where(.wp-block-test-clamp-me){font-size: clamp(27.894px, 1.743rem + ((1vw - 3.2px) * 1.571), 48px);}.has-pickles-font-size{font-size: var(--wp--preset--font-size--pickles) !important;}.has-toast-font-size{font-size: var(--wp--preset--font-size--toast) !important;}', + $theme_json->get_stylesheet( array( 'styles', 'variables', 'presets' ), null, array( 'skip_root_layout_styles' => true ) ) ); } @@ -3524,9 +3418,8 @@ public function test_get_property_value_valid() { ) ); - $color_styles = ':root :where(body){background-color: #ffffff;color: #000000;}:root :where(.wp-element-button, .wp-block-button__link){background-color: #000000;color: #ffffff;}'; - $expected = static::$base_styles . $color_styles; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); + $expected = ':root :where(body){background-color: #ffffff;color: #000000;}:root :where(.wp-element-button, .wp-block-button__link){background-color: #000000;color: #ffffff;}'; + $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } /** @@ -3602,9 +3495,8 @@ public function test_get_property_value_loop() { ) ); - $color_styles = ':root :where(body){background-color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; - $expected = static::$base_styles . $color_styles; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); + $expected = ':root :where(body){background-color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; + $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } /** @@ -3635,9 +3527,8 @@ public function test_get_property_value_recursion() { ) ); - $color_styles = ':root :where(body){background-color: #ffffff;color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; - $expected = static::$base_styles . $color_styles; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); + $expected = ':root :where(body){background-color: #ffffff;color: #ffffff;}:root :where(.wp-element-button, .wp-block-button__link){color: #ffffff;}'; + $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } /** @@ -3659,9 +3550,8 @@ public function test_get_property_value_self() { ) ); - $color_styles = ':root :where(body){background-color: #ffffff;}'; - $expected = static::$base_styles . $color_styles; - $this->assertSame( $expected, $theme_json->get_stylesheet() ); + $expected = ':root :where(body){background-color: #ffffff;}'; + $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_styles_for_block_with_padding_aware_alignments() { @@ -3723,7 +3613,7 @@ public function test_get_styles_for_block_without_padding_aware_alignments() { $this->assertSame( $expected, $root_rules . $style_rules ); } - public function test_get_styles_for_block_with_content_width() { + public function test_get_styles_with_content_width() { $theme_json = new WP_Theme_JSON_Gutenberg( array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, @@ -3741,10 +3631,8 @@ public function test_get_styles_for_block_with_content_width() { 'selector' => 'body', ); - $expected = ':root { --wp--style--global--content-size: 800px;--wp--style--global--wide-size: 1000px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; - $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ); - $style_rules = $theme_json->get_styles_for_block( $metadata ); - $this->assertSame( $expected, $root_rules . $style_rules ); + $expected = ':root { --wp--style--global--content-size: 800px;--wp--style--global--wide-size: 1000px; }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; + $this->assertSame( $expected, $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata ) ); } public function test_get_styles_with_appearance_tools() { @@ -3762,9 +3650,8 @@ public function test_get_styles_with_appearance_tools() { 'selector' => 'body', ); - $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: ; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: ; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1;margin-block-end: 0;}.is-layout-flex {gap: 1;}.is-layout-grid {gap: 1;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; - $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ); - $this->assertSame( $expected, $root_rules ); + $expected = ':where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: ; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: ; }.is-layout-flow > :first-child{margin-block-start: 0;}.is-layout-flow > :last-child{margin-block-end: 0;}.is-layout-flow > *{margin-block-start: 1;margin-block-end: 0;}.is-layout-constrained > :first-child{margin-block-start: 0;}.is-layout-constrained > :last-child{margin-block-end: 0;}.is-layout-constrained > *{margin-block-start: 1;margin-block-end: 0;}.is-layout-flex {gap: 1;}.is-layout-grid {gap: 1;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}'; + $this->assertSame( $expected, $theme_json->get_root_layout_rules( WP_Theme_JSON_Gutenberg::ROOT_BLOCK_SELECTOR, $metadata ) ); } public function test_sanitization() { @@ -4643,7 +4530,6 @@ public function data_set_spacing_sizes_when_invalid() { * @param array $expected_output Expected output from data provider. */ public function test_update_separator_declarations( $separator_block_settings, $expected_output ) { - // If only background is defined, test that includes border-color to the style so it is applied on the front end. $theme_json = new WP_Theme_JSON_Gutenberg( array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, @@ -4656,9 +4542,11 @@ public function test_update_separator_declarations( $separator_block_settings, $ 'default' ); - $stylesheet = $theme_json->get_stylesheet( array( 'styles' ) ); - - $this->assertSame( $expected_output, $stylesheet ); + $separator_node = array( + 'path' => array( 'styles', 'blocks', 'core/separator' ), + 'selector' => '.wp-block-separator', + ); + $this->assertSame( $expected_output, $theme_json->get_styles_for_block( $separator_node ) ); } /** @@ -4675,7 +4563,7 @@ public function data_update_separator_declarations() { 'background' => 'blue', ), ), - 'expected_output' => static::$base_styles . ':root :where(.wp-block-separator){background-color: blue;color: blue;}', + 'expected_output' => ':root :where(.wp-block-separator){background-color: blue;color: blue;}', ), // If background and text are defined, do not include border-color, as text color is enough. 'background and text, no border-color' => array( @@ -4685,7 +4573,7 @@ public function data_update_separator_declarations() { 'text' => 'red', ), ), - 'expected_output' => static::$base_styles . ':root :where(.wp-block-separator){background-color: blue;color: red;}', + 'expected_output' => ':root :where(.wp-block-separator){background-color: blue;color: red;}', ), // If only text is defined, do not include border-color, as by itself is enough. 'only text' => array( @@ -4694,7 +4582,7 @@ public function data_update_separator_declarations() { 'text' => 'red', ), ), - 'expected_output' => static::$base_styles . ':root :where(.wp-block-separator){color: red;}', + 'expected_output' => ':root :where(.wp-block-separator){color: red;}', ), // If background, text, and border-color are defined, include everything, CSS specificity will decide which to apply. 'background, text, and border-color' => array( @@ -4707,7 +4595,7 @@ public function data_update_separator_declarations() { 'color' => 'pink', ), ), - 'expected_output' => static::$base_styles . ':root :where(.wp-block-separator){background-color: blue;border-color: pink;color: red;}', + 'expected_output' => ':root :where(.wp-block-separator){background-color: blue;border-color: pink;color: red;}', ), // If background and border color are defined, include everything, CSS specificity will decide which to apply. 'background, and border-color' => array( @@ -4719,7 +4607,7 @@ public function data_update_separator_declarations() { 'color' => 'pink', ), ), - 'expected_output' => static::$base_styles . ':root :where(.wp-block-separator){background-color: blue;border-color: pink;}', + 'expected_output' => ':root :where(.wp-block-separator){background-color: blue;border-color: pink;}', ), ); } @@ -4782,10 +4670,10 @@ public function test_get_shadow_styles_for_blocks() { ) ); - $global_styles = ':root{--wp--preset--shadow--natural: 5px 5px 0 0 black;}' . static::$base_styles; + $variable_styles = ':root{--wp--preset--shadow--natural: 5px 5px 0 0 black;}'; $element_styles = ':root :where(a:where(:not(.wp-element-button))){box-shadow: var(--wp--preset--shadow--natural);}:root :where(.wp-element-button, .wp-block-button__link){box-shadow: var(--wp--preset--shadow--natural);}:root :where(p){box-shadow: var(--wp--preset--shadow--natural);}'; - $expected_styles = $global_styles . $element_styles; - $this->assertSame( $expected_styles, $theme_json->get_stylesheet() ); + $expected_styles = $variable_styles . $element_styles; + $this->assertSame( $expected_styles, $theme_json->get_stylesheet( array( 'styles', 'presets', 'variables' ), null, array( 'skip_root_layout_styles' => true ) ) ); } public function test_get_top_level_background_image_styles() { @@ -4801,36 +4689,17 @@ public function test_get_top_level_background_image_styles() { 'backgroundRepeat' => 'no-repeat', 'backgroundPosition' => 'center center', ), - 'blocks' => array( - 'core/paragraph' => array( - 'background' => array( - 'backgroundImage' => array( - 'url' => 'http://example.org/image.png', - ), - 'backgroundSize' => 'cover', - 'backgroundRepeat' => 'no-repeat', - 'backgroundPosition' => 'center center', - ), - ), - ), - 'elements' => array( - 'button' => array( - 'background' => array( - 'backgroundImage' => array( - 'url' => 'http://example.org/image.png', - ), - 'backgroundSize' => 'cover', - 'backgroundRepeat' => 'no-repeat', - 'backgroundPosition' => 'center center', - ), - ), - ), ), ) ); - $expected_styles = ":where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}"; - $this->assertSame( $expected_styles, $theme_json->get_stylesheet(), 'Styles returned from "::get_stylesheet()" with top-level background styles type does not match expectations' ); + $body_node = array( + 'path' => array( 'styles' ), + 'selector' => 'body', + ); + + $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}"; + $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background styles type does not match expectations' ); $theme_json = new WP_Theme_JSON_Gutenberg( array( @@ -4846,8 +4715,8 @@ public function test_get_top_level_background_image_styles() { ) ); - $expected_styles = ":where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}"; - $this->assertSame( $expected_styles, $theme_json->get_stylesheet(), 'Styles returned from "::get_stylesheet()" with top-level background image as string type does not match expectations' ); + $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}"; + $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background image as string type does not match expectations' ); } /**