wordpress-develop/tests/phpunit/tests/theme/wpThemeJsonResolver.php
Jb Audras 66055a520d Editor: Ensure Global styles values are reset in the site editor.
This changeset fixes a bug by which the reset function of the global styles sidebar would not work as expected in the site editor. It reverts [54517] and adds related unit tests.

Props oandregal, ntsekouras, youknowriad, hellofromTonya.
Fixes #57824
See #56467


git-svn-id: https://develop.svn.wordpress.org/trunk@55448 602fd350-edb4-49c9-b593-d223f7449a82
2023-03-01 16:15:27 +00:00

1021 lines
32 KiB
PHP

<?php
/**
* Test WP_Theme_JSON_Resolver class.
*
* @package WordPress
* @subpackage Theme
*
* @since 5.8.0
*
* @group themes
*/
class Tests_Theme_wpThemeJsonResolver extends WP_UnitTestCase {
/**
* Administrator ID.
*
* @var int
*/
protected static $administrator_id;
/**
* Theme root directory.
*
* @var string
*/
private $theme_root;
/**
* Original theme directory.
*
* @var string
*/
private $orig_theme_dir;
/**
* WP_Theme_JSON_Resolver::$blocks_cache property.
*
* @var ReflectionProperty
*/
private static $property_blocks_cache;
/**
* Original value of the WP_Theme_JSON_Resolver::$blocks_cache property.
*
* @var array
*/
private static $property_blocks_cache_orig_value;
/**
* WP_Theme_JSON_Resolver::$core property.
*
* @var ReflectionProperty
*/
private static $property_core;
/**
* Original value of the WP_Theme_JSON_Resolver::$core property.
*
* @var WP_Theme_JSON
*/
private static $property_core_orig_value;
public static function set_up_before_class() {
parent::set_up_before_class();
self::$administrator_id = self::factory()->user->create(
array(
'role' => 'administrator',
'user_email' => 'administrator@example.com',
)
);
static::$property_blocks_cache = new ReflectionProperty( WP_Theme_JSON_Resolver::class, 'blocks_cache' );
static::$property_blocks_cache->setAccessible( true );
static::$property_blocks_cache_orig_value = static::$property_blocks_cache->getValue();
static::$property_core = new ReflectionProperty( WP_Theme_JSON_Resolver::class, 'core' );
static::$property_core->setAccessible( true );
static::$property_core_orig_value = static::$property_core->getValue();
}
public static function tear_down_after_class() {
static::$property_blocks_cache->setValue( WP_Theme_JSON_Resolver::class, static::$property_blocks_cache_orig_value );
static::$property_core->setValue( WP_Theme_JSON_Resolver::class, static::$property_core_orig_value );
parent::tear_down_after_class();
}
public function set_up() {
parent::set_up();
$this->theme_root = realpath( DIR_TESTDATA . '/themedir1' );
$this->orig_theme_dir = $GLOBALS['wp_theme_directories'];
// /themes is necessary as theme.php functions assume /themes is the root if there is only one root.
$GLOBALS['wp_theme_directories'] = array( WP_CONTENT_DIR . '/themes', $this->theme_root );
add_filter( 'theme_root', array( $this, 'filter_set_theme_root' ) );
add_filter( 'stylesheet_root', array( $this, 'filter_set_theme_root' ) );
add_filter( 'template_root', array( $this, 'filter_set_theme_root' ) );
// Clear caches.
wp_clean_themes_cache();
unset( $GLOBALS['wp_themes'] );
}
public function tear_down() {
$GLOBALS['wp_theme_directories'] = $this->orig_theme_dir;
wp_clean_themes_cache();
unset( $GLOBALS['wp_themes'] );
// Reset data between tests.
wp_clean_theme_json_cache();
parent::tear_down();
}
public function filter_set_theme_root() {
return $this->theme_root;
}
public function filter_set_locale_to_polish() {
return 'pl_PL';
}
/**
* @ticket 52991
* @ticket 54336
* @ticket 56611
*/
public function test_translations_are_applied() {
add_filter( 'locale', array( $this, 'filter_set_locale_to_polish' ) );
load_textdomain( 'block-theme', realpath( DIR_TESTDATA . '/languages/themes/block-theme-pl_PL.mo' ) );
switch_theme( 'block-theme' );
$theme_data = WP_Theme_JSON_Resolver::get_theme_data();
$style_variations = WP_Theme_JSON_Resolver::get_style_variations();
unload_textdomain( 'block-theme' );
remove_filter( 'locale', array( $this, 'filter_set_locale_to_polish' ) );
$this->assertSame( 'block-theme', wp_get_theme()->get( 'TextDomain' ) );
$this->assertSame( 'Motyw blokowy', $theme_data->get_data()['title'] );
$this->assertSameSets(
array(
'color' => array(
'custom' => false,
'customGradient' => false,
'palette' => array(
'theme' => array(
array(
'slug' => 'light',
'name' => 'Jasny',
'color' => '#f5f7f9',
),
array(
'slug' => 'dark',
'name' => 'Ciemny',
'color' => '#000',
),
),
),
'gradients' => array(
'theme' => array(
array(
'name' => 'Custom gradient',
'gradient' => 'linear-gradient(135deg,rgba(0,0,0) 0%,rgb(0,0,0) 100%)',
'slug' => 'custom-gradient',
),
),
),
'duotone' => array(
'theme' => array(
array(
'colors' => array( '#333333', '#aaaaaa' ),
'slug' => 'custom-duotone',
'name' => 'Custom Duotone',
),
),
),
),
'typography' => array(
'customFontSize' => false,
'lineHeight' => true,
'fontSizes' => array(
'theme' => array(
array(
'name' => 'Custom',
'slug' => 'custom',
'size' => '100px',
),
),
),
),
'spacing' => array(
'units' => array( 'rem' ),
'padding' => true,
'blockGap' => true,
),
'blocks' => array(
'core/paragraph' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'light',
'name' => 'Jasny',
'color' => '#f5f7f9',
),
),
),
),
),
),
),
$theme_data->get_settings()
);
$custom_templates = $theme_data->get_custom_templates();
$this->assertArrayHasKey( 'page-home', $custom_templates );
$this->assertSame(
$custom_templates['page-home'],
array(
'title' => 'Szablon strony głównej',
'postTypes' => array( 'page' ),
)
);
$this->assertSameSets(
array(
'small-header' => array(
'title' => 'Mały nagłówek',
'area' => 'header',
),
),
$theme_data->get_template_parts()
);
$this->assertSame(
'Wariant motywu blokowego',
$style_variations[1]['title']
);
}
private function get_registered_block_names( $hard_reset = false ) {
static $expected_block_names;
if ( ! $hard_reset && ! empty( $expected_block_names ) ) {
return $expected_block_names;
}
$expected_block_names = array();
$resolver = WP_Block_Type_Registry::get_instance();
$blocks = $resolver->get_all_registered();
foreach ( array_keys( $blocks ) as $block_name ) {
$expected_block_names[ $block_name ] = true;
}
return $expected_block_names;
}
/**
* Tests when WP_Theme_JSON_Resolver::$blocks_cache is empty or does not match
* the all registered blocks.
*
* Though this is a non-public method, it is vital to other functionality.
* Therefore, tests are provided to validate it functions as expected.
*
* @dataProvider data_has_same_registered_blocks_when_all_blocks_not_cached
* @ticket 56467
*
* @param string $origin The origin to test.
*/
public function test_has_same_registered_blocks_when_all_blocks_not_cached( $origin, array $cache = array() ) {
$has_same_registered_blocks = new ReflectionMethod( WP_Theme_JSON_Resolver::class, 'has_same_registered_blocks' );
$has_same_registered_blocks->setAccessible( true );
$expected_cache = $this->get_registered_block_names();
// Set up the blocks cache for the origin.
$blocks_cache = static::$property_blocks_cache->getValue();
$blocks_cache[ $origin ] = $cache;
static::$property_blocks_cache->setValue( null, $blocks_cache );
$this->assertFalse( $has_same_registered_blocks->invoke( null, $origin ), 'WP_Theme_JSON_Resolver::has_same_registered_blocks() should return false when same blocks are not cached' );
$blocks_cache = static::$property_blocks_cache->getValue();
$this->assertSameSets( $expected_cache, $blocks_cache[ $origin ], 'WP_Theme_JSON_Resolver::$blocks_cache should contain all expected block names for the given origin' );
}
/**
* Data provider.
*
* @return array
*/
public function data_has_same_registered_blocks_when_all_blocks_not_cached() {
return array(
'origin: core; cache: empty' => array(
'origin' => 'core',
),
'origin: blocks; cache: empty' => array(
'origin' => 'blocks',
),
'origin: theme; cache: empty' => array(
'origin' => 'theme',
),
'origin: user; cache: empty' => array(
'origin' => 'user',
),
'origin: core; cache: not empty' => array(
'origin' => 'core',
'cache' => array(
'core/block' => true,
),
),
'origin: blocks; cache: not empty' => array(
'origin' => 'blocks',
'cache' => array(
'core/block' => true,
'core/comments' => true,
),
),
'origin: theme; cache: not empty' => array(
'origin' => 'theme',
'cache' => array(
'core/cover' => true,
),
),
'origin: user; cache: not empty' => array(
'origin' => 'user',
'cache' => array(
'core/gallery' => true,
),
),
);
}
/**
* Tests when WP_Theme_JSON_Resolver::$blocks_cache is empty or does not match
* the all registered blocks.
*
* Though this is a non-public method, it is vital to other functionality.
* Therefore, tests are provided to validate it functions as expected.
*
* @dataProvider data_has_same_registered_blocks_when_all_blocks_are_cached
* @ticket 56467
*
* @param string $origin The origin to test.
*/
public function test_has_same_registered_blocks_when_all_blocks_are_cached( $origin ) {
$has_same_registered_blocks = new ReflectionMethod( WP_Theme_JSON_Resolver::class, 'has_same_registered_blocks' );
$has_same_registered_blocks->setAccessible( true );
$expected_cache = $this->get_registered_block_names();
// Set up the cache with all registered blocks.
$blocks_cache = static::$property_blocks_cache->getValue();
$blocks_cache[ $origin ] = $this->get_registered_block_names();
static::$property_blocks_cache->setValue( null, $blocks_cache );
$this->assertTrue( $has_same_registered_blocks->invoke( null, $origin ), 'WP_Theme_JSON_Resolver::has_same_registered_blocks() should return true when using the cache' );
$this->assertSameSets( $expected_cache, $blocks_cache[ $origin ], 'WP_Theme_JSON_Resolver::$blocks_cache should contain all expected block names for the given origin' );
}
/**
* Data provider.
*
* @return array
*/
public function data_has_same_registered_blocks_when_all_blocks_are_cached() {
return array(
'core' => array( 'core' ),
'blocks' => array( 'blocks' ),
'theme' => array( 'theme' ),
'user' => array( 'user' ),
);
}
/**
* @dataProvider data_get_core_data
* @covers WP_Theme_JSON_Resolver::get_core_data
* @ticket 56467
*/
public function test_get_core_data( $should_fire_filter, $core_is_cached, $blocks_are_cached ) {
wp_clean_theme_json_cache();
// If should cache core, then fire the method to cache it before running the tests.
if ( $core_is_cached ) {
WP_Theme_JSON_Resolver::get_core_data();
}
// If should cache registered blocks, then set them up before running the tests.
if ( $blocks_are_cached ) {
$blocks_cache = static::$property_blocks_cache->getValue();
$blocks_cache['core'] = $this->get_registered_block_names();
static::$property_blocks_cache->setValue( null, $blocks_cache );
}
$expected_filter_count = did_filter( 'wp_theme_json_data_default' );
$actual = WP_Theme_JSON_Resolver::get_core_data();
if ( $should_fire_filter ) {
$expected_filter_count++;
}
$this->assertSame( $expected_filter_count, did_filter( 'wp_theme_json_data_default' ), 'The filter "wp_theme_json_data_default" should fire the given number of times' );
$this->assertInstanceOf( WP_Theme_JSON::class, $actual, 'WP_Theme_JSON_Resolver::get_core_data() should return instance of WP_Theme_JSON' );
$this->assertSame( static::$property_core->getValue(), $actual, 'WP_Theme_JSON_Resolver::$core property should be the same object as returned from WP_Theme_JSON_Resolver::get_core_data()' );
}
/**
* Data provider.
*
* @return array
*/
public function data_get_core_data() {
return array(
'When both caches are empty' => array(
'should_fire_filter' => true,
'core_is_cached' => false,
'blocks_are_cached' => false,
),
'When the blocks_cache is not empty and matches' => array(
'should_fire_filter' => true,
'core_is_cached' => false,
'blocks_are_cached' => true,
),
'When blocks_cache is empty but core cache is not' => array(
'should_fire_filter' => true,
'core_is_cached' => true,
'blocks_are_cached' => false,
),
'When both caches are not empty' => array(
'should_fire_filter' => true,
'core_is_cached' => true,
'blocks_are_cached' => false,
),
);
}
/**
* @ticket 54336
*/
public function test_add_theme_supports_are_loaded_for_themes_without_theme_json() {
switch_theme( 'default' );
$color_palette = array(
array(
'name' => 'Primary',
'slug' => 'primary',
'color' => '#F00',
),
array(
'name' => 'Secondary',
'slug' => 'secondary',
'color' => '#0F0',
),
array(
'name' => 'Tertiary',
'slug' => 'tertiary',
'color' => '#00F',
),
);
add_theme_support( 'editor-color-palette', $color_palette );
add_theme_support( 'custom-line-height' );
$settings = WP_Theme_JSON_Resolver::get_theme_data()->get_settings();
remove_theme_support( 'custom-line-height' );
remove_theme_support( 'editor-color-palette' );
$this->assertFalse( wp_theme_has_theme_json() );
$this->assertTrue( $settings['typography']['lineHeight'] );
$this->assertSame( $color_palette, $settings['color']['palette']['theme'] );
}
/**
* @ticket 54336
* @ticket 56611
*/
public function test_merges_child_theme_json_into_parent_theme_json() {
switch_theme( 'block-theme-child' );
$actual_settings = WP_Theme_JSON_Resolver::get_theme_data()->get_settings();
$expected_settings = array(
'color' => array(
'custom' => false,
'customGradient' => false,
'duotone' => array(
'theme' => array(
array(
'colors' => array( '#333333', '#aaaaaa' ),
'name' => 'Custom Duotone',
'slug' => 'custom-duotone',
),
),
),
'gradients' => array(
'theme' => array(
array(
'name' => 'Custom gradient',
'gradient' => 'linear-gradient(135deg,rgba(0,0,0) 0%,rgb(0,0,0) 100%)',
'slug' => 'custom-gradient',
),
),
),
'palette' => array(
'theme' => array(
array(
'slug' => 'light',
'name' => 'Light',
'color' => '#f3f4f6',
),
array(
'slug' => 'primary',
'name' => 'Primary',
'color' => '#3858e9',
),
array(
'slug' => 'dark',
'name' => 'Dark',
'color' => '#111827',
),
),
),
'link' => true,
),
'typography' => array(
'customFontSize' => false,
'lineHeight' => true,
'fontSizes' => array(
'theme' => array(
array(
'name' => 'Custom',
'slug' => 'custom',
'size' => '100px',
),
),
),
),
'spacing' => array(
'blockGap' => true,
'units' => array( 'rem' ),
'padding' => true,
),
'blocks' => array(
'core/paragraph' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'light',
'name' => 'Light',
'color' => '#f5f7f9',
),
),
),
),
),
'core/post-title' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'light',
'name' => 'Light',
'color' => '#f3f4f6',
),
),
),
),
),
),
);
wp_recursive_ksort( $actual_settings );
wp_recursive_ksort( $expected_settings );
// Should merge settings.
$this->assertSame(
$expected_settings,
$actual_settings
);
$this->assertSame(
WP_Theme_JSON_Resolver::get_theme_data()->get_custom_templates(),
array(
'page-home' => array(
'title' => 'Homepage',
'postTypes' => array( 'page' ),
),
'custom-single-post-template' => array(
'title' => 'Custom Single Post template',
'postTypes' => array( 'post' ),
),
)
);
}
/**
* @covers WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles
*/
public function test_get_user_data_from_wp_global_styles_does_not_use_uncached_queries() {
// Switch to a theme that does have support.
switch_theme( 'block-theme' );
wp_set_current_user( self::$administrator_id );
$theme = wp_get_theme();
WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
$global_styles_query_count = 0;
add_filter(
'query',
function( $query ) use ( &$global_styles_query_count ) {
if ( preg_match( '#post_type = \'wp_global_styles\'#', $query ) ) {
$global_styles_query_count++;
}
return $query;
}
);
for ( $i = 0; $i < 3; $i++ ) {
WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
wp_clean_theme_json_cache();
}
$this->assertSame( 0, $global_styles_query_count, 'Unexpected SQL queries detected for the wp_global_style post type prior to creation.' );
$user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
$this->assertEmpty( $user_cpt, 'User CPT is expected to be empty.' );
$user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme, true );
$this->assertNotEmpty( $user_cpt, 'User CPT is expected not to be empty.' );
$global_styles_query_count = 0;
for ( $i = 0; $i < 3; $i++ ) {
$new_user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
wp_clean_theme_json_cache();
$this->assertSameSets( $user_cpt, $new_user_cpt, "User CPTs do not match on run {$i}." );
}
$this->assertSame( 1, $global_styles_query_count, 'Unexpected SQL queries detected for the wp_global_style post type after creation.' );
}
/**
* @covers WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles
*/
public function test_get_user_data_from_wp_global_styles_does_not_use_uncached_queries_for_logged_out_users() {
// Switch to a theme that does have support.
switch_theme( 'block-theme' );
$theme = wp_get_theme();
WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
$query_count = get_num_queries();
for ( $i = 0; $i < 3; $i++ ) {
WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
wp_clean_theme_json_cache();
}
$query_count = get_num_queries() - $query_count;
$this->assertSame( 0, $query_count, 'Unexpected SQL queries detected for the wp_global_style post type prior to creation.' );
$user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
$this->assertEmpty( $user_cpt, 'User CPT is expected to be empty.' );
}
/**
* @ticket 56945
* @covers WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles
*/
public function test_get_user_data_from_wp_global_styles_does_not_run_for_theme_without_support() {
// The 'default' theme does not support theme.json.
switch_theme( 'default' );
wp_set_current_user( self::$administrator_id );
$theme = wp_get_theme();
$start_queries = get_num_queries();
// When theme.json is not supported, the method should not run a query and always return an empty result.
$user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
$this->assertEmpty( $user_cpt, 'User CPT is expected to be empty.' );
$this->assertSame( 0, get_num_queries() - $start_queries, 'Unexpected SQL query detected for theme without theme.json support.' );
$user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme, true );
$this->assertEmpty( $user_cpt, 'User CPT is expected to be empty.' );
$this->assertSame( 0, get_num_queries() - $start_queries, 'Unexpected SQL query detected for theme without theme.json support.' );
}
/**
* @ticket 55392
* @covers WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles
*/
public function test_get_user_data_from_wp_global_styles_does_exist() {
// Switch to a theme that does have support.
switch_theme( 'block-theme' );
$theme = wp_get_theme();
$post1 = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme, true );
$this->assertIsArray( $post1 );
$this->assertArrayHasKey( 'ID', $post1 );
wp_delete_post( $post1['ID'], true );
$post2 = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme, true );
$this->assertIsArray( $post2 );
$this->assertArrayHasKey( 'ID', $post2 );
}
/**
* @ticket 55392
* @covers WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles
*/
public function test_get_user_data_from_wp_global_styles_create_post() {
// Switch to a theme that does have support.
switch_theme( 'block-theme' );
$theme = wp_get_theme( 'testing' );
$post1 = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
$this->assertIsArray( $post1 );
$this->assertSameSets( array(), $post1 );
$post2 = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme );
$this->assertIsArray( $post2 );
$this->assertSameSets( array(), $post2 );
$post3 = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme, true );
$this->assertIsArray( $post3 );
$this->assertArrayHasKey( 'ID', $post3 );
}
/**
* @ticket 55392
* @covers WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles
*/
public function test_get_user_data_from_wp_global_styles_filter_state() {
// Switch to a theme that does have support.
switch_theme( 'block-theme' );
$theme = wp_get_theme( 'foo' );
$post1 = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme, true, array( 'publish' ) );
$this->assertIsArray( $post1 );
$this->assertArrayHasKey( 'ID', $post1 );
$post2 = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme, false, array( 'draft' ) );
$this->assertIsArray( $post2 );
$this->assertSameSets( array(), $post2 );
}
/**
* @ticket 56835
* @covers WP_Theme_JSON_Resolver::get_theme_data
*/
public function test_get_theme_data_theme_supports_overrides_theme_json() {
// Test that get_theme_data() returns a WP_Theme_JSON object.
$theme_json_resolver = new WP_Theme_JSON_Resolver();
$theme_data = $theme_json_resolver->get_theme_data();
$this->assertInstanceOf( 'WP_Theme_JSON', $theme_data, 'Theme data should be an instance of WP_Theme_JSON.' );
// Test that wp_theme_json_data_theme filter has been called.
$this->assertGreaterThan( 0, did_filter( 'wp_theme_json_data_default' ), 'The filter "wp_theme_json_data_default" should fire.' );
// Test that data from theme.json is backfilled from existing theme supports.
$previous_settings = $theme_data->get_settings();
$previous_line_height = $previous_settings['typography']['lineHeight'];
$this->assertFalse( $previous_line_height, 'lineHeight setting from theme.json should be false.' );
add_theme_support( 'custom-line-height' );
$current_settings = $theme_json_resolver->get_theme_data()->get_settings();
$line_height = $current_settings['typography']['lineHeight'];
$this->assertTrue( $line_height, 'lineHeight setting after add_theme_support() should be true.' );
}
/**
* @ticket 56945
* @covers WP_Theme_JSON_Resolver::get_theme_data
*/
public function test_get_theme_data_does_not_parse_theme_json_if_not_present() {
// The 'default' theme does not support theme.json.
switch_theme( 'default' );
$theme_json_resolver = new WP_Theme_JSON_Resolver();
// Force-unset $i18n_schema property to "unload" translation schema.
$property = new ReflectionProperty( $theme_json_resolver, 'i18n_schema' );
$property->setAccessible( true );
$property->setValue( null );
// A completely empty theme.json data set still has the 'version' key when parsed.
$empty_theme_json = array( 'version' => WP_Theme_JSON::LATEST_SCHEMA );
// Call using 'with_supports' set to false, so that the method only considers theme.json.
$theme_data = $theme_json_resolver->get_theme_data( array(), array( 'with_supports' => false ) );
$this->assertInstanceOf( 'WP_Theme_JSON', $theme_data, 'Theme data should be an instance of WP_Theme_JSON.' );
$this->assertSame( $empty_theme_json, $theme_data->get_raw_data(), 'Theme data should be empty without theme support.' );
$this->assertNull( $property->getValue(), 'Theme i18n schema should not have been loaded without theme support.' );
}
/**
* Tests that get_merged_data returns the data merged up to the proper origin.
*
* @ticket 57545
*
* @covers WP_Theme_JSON_Resolver::get_merged_data
*
* @dataProvider data_get_merged_data_returns_origin
*
* @param string $origin What origin to get data from.
* @param bool $core_palette Whether the core palette is present.
* @param string $core_palette_text Message.
* @param string $block_styles Whether the block styles are present.
* @param string $block_styles_text Message.
* @param bool $theme_palette Whether the theme palette is present.
* @param string $theme_palette_text Message.
* @param bool $user_palette Whether the user palette is present.
* @param string $user_palette_text Message.
*/
public function test_get_merged_data_returns_origin( $origin, $core_palette, $core_palette_text, $block_styles, $block_styles_text, $theme_palette, $theme_palette_text, $user_palette, $user_palette_text ) {
// Make sure there is data from the blocks origin.
register_block_type(
'my/block-with-styles',
array(
'api_version' => 2,
'attributes' => array(
'borderColor' => array(
'type' => 'string',
),
'style' => array(
'type' => 'object',
),
),
'supports' => array(
'__experimentalStyle' => array(
'typography' => array(
'fontSize' => '42rem',
),
),
),
)
);
// Make sure there is data from the theme origin.
switch_theme( 'block-theme' );
// Make sure there is data from the user origin.
wp_set_current_user( self::$administrator_id );
$user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( wp_get_theme(), true );
$config = json_decode( $user_cpt['post_content'], true );
$config['settings']['color']['palette']['custom'] = array(
array(
'color' => 'hotpink',
'name' => 'My color',
'slug' => 'my-color',
),
);
$user_cpt['post_content'] = wp_json_encode( $config );
wp_update_post( $user_cpt, true, false );
$theme_json = WP_Theme_JSON_Resolver::get_merged_data( $origin );
$settings = $theme_json->get_settings();
$styles = $theme_json->get_styles_block_nodes();
$styles = array_filter(
$styles,
static function( $element ) {
return isset( $element['name'] ) && 'my/block-with-styles' === $element['name'];
}
);
unregister_block_type( 'my/block-with-styles' );
$this->assertSame( $core_palette, isset( $settings['color']['palette']['default'] ), $core_palette_text );
$this->assertSame( $block_styles, count( $styles ) === 1, $block_styles_text );
$this->assertSame( $theme_palette, isset( $settings['color']['palette']['theme'] ), $theme_palette_text );
$this->assertSame( $user_palette, isset( $settings['color']['palette']['custom'] ), $user_palette_text );
}
/**
* Tests that get_merged_data returns the data merged up to the proper origin
* and that the core values have the proper data.
*
* @ticket 57824
*
* @covers WP_Theme_JSON_Resolver::get_merged_data
*
*/
public function test_get_merged_data_returns_origin_proper() {
// Make sure the theme has a theme.json
// though it doesn't have any data for styles.spacing.padding.
switch_theme( 'block-theme' );
// Make sure the user defined some data for styles.spacing.padding.
wp_set_current_user( self::$administrator_id );
$user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( wp_get_theme(), true );
$config = json_decode( $user_cpt['post_content'], true );
$config['styles']['spacing']['padding'] = array(
'top' => '23px',
'left' => '23px',
'bottom' => '23px',
'right' => '23px',
);
$user_cpt['post_content'] = wp_json_encode( $config );
wp_update_post( $user_cpt, true, false );
// Query data from the user origin and then for the theme origin.
$theme_json_user = WP_Theme_JSON_Resolver::get_merged_data( 'custom' );
$padding_user = $theme_json_user->get_raw_data()['styles']['spacing']['padding'];
$theme_json_theme = WP_Theme_JSON_Resolver::get_merged_data( 'theme' );
$padding_theme = $theme_json_theme->get_raw_data()['styles']['spacing']['padding'];
$this->assertSame( '23px', $padding_user['top'] );
$this->assertSame( '23px', $padding_user['right'] );
$this->assertSame( '23px', $padding_user['bottom'] );
$this->assertSame( '23px', $padding_user['left'] );
$this->assertSame( '0px', $padding_theme['top'] );
$this->assertSame( '0px', $padding_theme['right'] );
$this->assertSame( '0px', $padding_theme['bottom'] );
$this->assertSame( '0px', $padding_theme['left'] );
}
/**
* Data provider.
*
* @return array[]
*/
public function data_get_merged_data_returns_origin() {
return array(
'origin_default' => array(
'origin' => 'default',
'core_palette' => true,
'core_palette_text' => 'Core palette must be present',
'block_styles' => false,
'block_styles_text' => 'Block styles should not be present',
'theme_palette' => false,
'theme_palette_text' => 'Theme palette should not be present',
'user_palette' => false,
'user_palette_text' => 'User palette should not be present',
),
'origin_blocks' => array(
'origin' => 'blocks',
'core_palette' => true,
'core_palette_text' => 'Core palette must be present',
'block_styles' => true,
'block_styles_text' => 'Block styles must be present',
'theme_palette' => false,
'theme_palette_text' => 'Theme palette should not be present',
'user_palette' => false,
'user_palette_text' => 'User palette should not be present',
),
'origin_theme' => array(
'origin' => 'theme',
'core_palette' => true,
'core_palette_text' => 'Core palette must be present',
'block_styles' => true,
'block_styles_text' => 'Block styles must be present',
'theme_palette' => true,
'theme_palette_text' => 'Theme palette must be present',
'user_palette' => false,
'user_palette_text' => 'User palette should not be present',
),
'origin_custom' => array(
'origin' => 'custom',
'core_palette' => true,
'core_palette_text' => 'Core palette must be present',
'block_styles' => true,
'block_styles_text' => 'Block styles must be present',
'theme_palette' => true,
'theme_palette_text' => 'Theme palette must be present',
'user_palette' => true,
'user_palette_text' => 'User palette must be present',
),
);
}
/**
* Tests that get_style_variations returns all variations, including parent theme variations if the theme is a child,
* and that the child variation overwrites the parent variation of the same name.
*
* @ticket 57545
*
* @covers WP_Theme_JSON_Resolver::get_style_variations
**/
public function test_get_style_variations_returns_all_variations() {
// Switch to a child theme.
switch_theme( 'block-theme-child' );
wp_set_current_user( self::$administrator_id );
$actual_settings = WP_Theme_JSON_Resolver::get_style_variations();
$expected_settings = array(
array(
'version' => 2,
'title' => 'variation-b',
'settings' => array(
'blocks' => array(
'core/post-title' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'dark',
'name' => 'Dark',
'color' => '#010101',
),
),
),
),
),
),
),
),
array(
'version' => 2,
'title' => 'Block theme variation',
'settings' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'foreground',
'name' => 'Foreground',
'color' => '#3F67C6',
),
),
),
),
),
'styles' => array(
'blocks' => array(
'core/post-title' => array(
'typography' => array(
'fontWeight' => '700',
),
),
),
),
),
);
wp_recursive_ksort( $actual_settings );
wp_recursive_ksort( $expected_settings );
$this->assertSame(
$expected_settings,
$actual_settings
);
}
}