From 2463bf7ec234a790eead3ff7f2775f059681fe65 Mon Sep 17 00:00:00 2001 From: Paul Bearne Date: Wed, 6 May 2026 16:31:46 -0400 Subject: [PATCH 1/4] Add unit tests for admin_color_scheme_picker() in wp-admin/includes/misc.php --- .../includes/misc/adminColorSchemePicker.php | 237 ++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php diff --git a/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php b/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php new file mode 100644 index 0000000000000..7e69d9ee82de5 --- /dev/null +++ b/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php @@ -0,0 +1,237 @@ +orig_wp_admin_css_colors = $_wp_admin_css_colors; + } + + public function tear_down() { + global $_wp_admin_css_colors; + $_wp_admin_css_colors = $this->orig_wp_admin_css_colors; + parent::tear_down(); + } + + /** + * @ticket 65184 + */ + public function test_admin_color_scheme_picker_default_selection() { + global $_wp_admin_css_colors; + + // Mock color schemes. + $_wp_admin_css_colors = array( + 'fresh' => (object) array( + 'name' => 'Default', + 'url' => 'fresh.css', + 'colors' => array( '#1d2327', '#2c3338', '#2271b1', '#72aee6' ), + 'icon_colors' => array( 'base' => '#a7aaad', 'focus' => '#72aee6', 'current' => '#fff' ), + ), + 'modern' => (object) array( + 'name' => 'Modern', + 'url' => 'modern.css', + 'colors' => array( '#1e1e1e', '#383838', '#007cba', '#e0e0e0' ), + 'icon_colors' => array( 'base' => '#f0f0f1', 'focus' => '#fff', 'current' => '#fff' ), + ), + ); + + $user_id = self::factory()->user->create( array( 'role' => 'subscriber' ) ); + wp_set_current_user( $user_id ); + + ob_start(); + admin_color_scheme_picker( $user_id ); + $output = ob_get_clean(); + + $this->assertStringContainsString( 'id="color-picker"', $output ); + $this->assertStringContainsString( 'value="modern"', $output ); + $this->assertStringContainsString( 'checked=\'checked\'', $output ); + $this->assertStringContainsString( 'name="admin_color"', $output ); + + // Verify "modern" is selected by default when no option is set. + $this->assertStringContainsString( 'id="admin_color_modern" type="radio" value="modern" checked=\'checked\'', $output ); + } + + /** + * @ticket 65184 + */ + public function test_admin_color_scheme_picker_custom_selection() { + global $_wp_admin_css_colors; + + $_wp_admin_css_colors = array( + 'fresh' => (object) array( + 'name' => 'Default', + 'url' => 'fresh.css', + 'colors' => array( '#1d2327' ), + 'icon_colors' => array( 'base' => '#a7aaad' ), + ), + 'blue' => (object) array( + 'name' => 'Blue', + 'url' => 'blue.css', + 'colors' => array( '#096484' ), + 'icon_colors' => array( 'base' => '#e5f8ff' ), + ), + 'modern' => (object) array( + 'name' => 'Modern', + 'url' => 'modern.css', + 'colors' => array( '#1e1e1e' ), + 'icon_colors' => array( 'base' => '#f0f0f1' ), + ), + ); + + $user_id = self::factory()->user->create( array( 'role' => 'subscriber' ) ); + update_user_meta( $user_id, 'admin_color', 'blue' ); + wp_set_current_user( $user_id ); + + ob_start(); + admin_color_scheme_picker( $user_id ); + $output = ob_get_clean(); + + $this->assertStringContainsString( 'value="blue"', $output ); + $this->assertStringContainsString( 'id="admin_color_blue" type="radio" value="blue" checked=\'checked\'', $output ); + $this->assertStringNotContainsString( 'id="admin_color_modern" type="radio" value="modern" checked=\'checked\'', $output ); + } + + /** + * @ticket 65184 + */ + public function test_admin_color_scheme_picker_invalid_selection_fallback() { + global $_wp_admin_css_colors; + + $_wp_admin_css_colors = array( + 'fresh' => (object) array( + 'name' => 'Default', + 'url' => 'fresh.css', + 'colors' => array( '#1d2327' ), + 'icon_colors' => array( 'base' => '#a7aaad' ), + ), + 'modern' => (object) array( + 'name' => 'Modern', + 'url' => 'modern.css', + 'colors' => array( '#1e1e1e' ), + 'icon_colors' => array( 'base' => '#f0f0f1' ), + ), + ); + + $user_id = self::factory()->user->create( array( 'role' => 'subscriber' ) ); + update_user_meta( $user_id, 'admin_color', 'non-existent' ); + wp_set_current_user( $user_id ); + + ob_start(); + admin_color_scheme_picker( $user_id ); + $output = ob_get_clean(); + + // Should fallback to 'modern'. + $this->assertStringContainsString( 'id="admin_color_modern" type="radio" value="modern" checked=\'checked\'', $output ); + } + + /** + * @ticket 65184 + */ + public function test_admin_color_scheme_picker_sorting() { + global $_wp_admin_css_colors; + + $_wp_admin_css_colors = array( + 'ocean' => (object) array( 'name' => 'Ocean', 'url' => '', 'colors' => array(), 'icon_colors' => array() ), + 'fresh' => (object) array( 'name' => 'Default', 'url' => '', 'colors' => array(), 'icon_colors' => array() ), + 'light' => (object) array( 'name' => 'Light', 'url' => '', 'colors' => array(), 'icon_colors' => array() ), + 'modern' => (object) array( 'name' => 'Modern', 'url' => '', 'colors' => array(), 'icon_colors' => array() ), + 'coffee' => (object) array( 'name' => 'Coffee', 'url' => '', 'colors' => array(), 'icon_colors' => array() ), + ); + + $user_id = self::factory()->user->create( array( 'role' => 'subscriber' ) ); + + ob_start(); + admin_color_scheme_picker( $user_id ); + $output = ob_get_clean(); + + // The function does ksort first, then if 'modern' exists, it merges with prioritized list. + // array( 'modern' => '', 'fresh' => '', 'light' => '' ) + $_wp_admin_css_colors + // The result should have modern, fresh, light first, then the rest sorted alphabetically. + + $dom = new DOMDocument(); + // Suppress warnings for HTML5 elements or invalid HTML. + libxml_use_internal_errors( true ); + $dom->loadHTML( $output ); + libxml_clear_errors(); + + $inputs = $dom->getElementsByTagName( 'input' ); + $found_colors = array(); + foreach ( $inputs as $input ) { + if ( 'radio' === $input->getAttribute( 'type' ) ) { + $found_colors[] = $input->getAttribute( 'value' ); + } + } + + $expected_order = array( 'modern', 'fresh', 'light', 'coffee', 'ocean' ); + $this->assertEquals( $expected_order, $found_colors, 'Color schemes should be ordered with modern, fresh, light first, followed by others alphabetically.' ); + } + + /** + * @ticket 65184 + */ + public function test_admin_color_scheme_picker_html_structure() { + global $_wp_admin_css_colors; + + $_wp_admin_css_colors = array( + 'modern' => (object) array( + 'name' => 'Modern Display Name', + 'url' => 'https://example.com/modern.css', + 'colors' => array( '#111', '#222' ), + 'icon_colors' => array( 'icons' => '#333' ), + ), + ); + + $user_id = self::factory()->user->create( array( 'role' => 'subscriber' ) ); + + ob_start(); + admin_color_scheme_picker( $user_id ); + $output = ob_get_clean(); + + $dom = new DOMDocument(); + libxml_use_internal_errors( true ); + $dom->loadHTML( $output ); + libxml_clear_errors(); + + $xpath = new DOMXPath( $dom ); + + // Check fieldset and legend. + $this->assertEquals( 1, $xpath->query( '//fieldset[@id="color-picker"]' )->length ); + $this->assertEquals( 1, $xpath->query( '//legend' )->length ); + + // Check radio input. + $radio = $xpath->query( '//input[@type="radio"][@value="modern"]' ); + $this->assertEquals( 1, $radio->length ); + $this->assertEquals( 'admin_color_modern', $radio->item( 0 )->getAttribute( 'id' ) ); + + // Check hidden inputs. + $this->assertEquals( 1, $xpath->query( '//input[@type="hidden"][@class="css_url"][@value="https://example.com/modern.css"]' )->length ); + + $icon_colors_input = $xpath->query( '//input[@type="hidden"][@class="icon_colors"]' ); + $this->assertEquals( 1, $icon_colors_input->length ); + $json_data = json_decode( $icon_colors_input->item( 0 )->getAttribute( 'value' ), true ); + $this->assertEquals( array( 'icons' => array( 'icons' => '#333' ) ), $json_data ); + + // Check label. + $label = $xpath->query( '//label[@for="admin_color_modern"]' ); + $this->assertEquals( 1, $label->length ); + $this->assertStringContainsString( 'Modern Display Name', $label->item( 0 )->nodeValue ); + + // Check color palette. + $this->assertEquals( 2, $xpath->query( '//div[@class="color-palette-shade"]' )->length ); + $this->assertStringContainsString( 'background-color: #111', $output ); + $this->assertStringContainsString( 'background-color: #222', $output ); + } +} From 7dcaab7504e9789f05f4bdf45d7b3fc8d588467f Mon Sep 17 00:00:00 2001 From: Paul Bearne Date: Wed, 6 May 2026 16:41:40 -0400 Subject: [PATCH 2/4] Refactor icon_colors array formatting in tests --- .../includes/misc/adminColorSchemePicker.php | 47 ++++++++++++++++--- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php b/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php index 7e69d9ee82de5..438c2d06050fc 100644 --- a/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php +++ b/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php @@ -38,13 +38,21 @@ public function test_admin_color_scheme_picker_default_selection() { 'name' => 'Default', 'url' => 'fresh.css', 'colors' => array( '#1d2327', '#2c3338', '#2271b1', '#72aee6' ), - 'icon_colors' => array( 'base' => '#a7aaad', 'focus' => '#72aee6', 'current' => '#fff' ), + 'icon_colors' => array( + 'base' => '#a7aaad', + 'focus' => '#72aee6', + 'current' => '#fff', + ), ), 'modern' => (object) array( 'name' => 'Modern', 'url' => 'modern.css', 'colors' => array( '#1e1e1e', '#383838', '#007cba', '#e0e0e0' ), - 'icon_colors' => array( 'base' => '#f0f0f1', 'focus' => '#fff', 'current' => '#fff' ), + 'icon_colors' => array( + 'base' => '#f0f0f1', + 'focus' => '#fff', + 'current' => '#fff', + ), ), ); @@ -144,11 +152,36 @@ public function test_admin_color_scheme_picker_sorting() { global $_wp_admin_css_colors; $_wp_admin_css_colors = array( - 'ocean' => (object) array( 'name' => 'Ocean', 'url' => '', 'colors' => array(), 'icon_colors' => array() ), - 'fresh' => (object) array( 'name' => 'Default', 'url' => '', 'colors' => array(), 'icon_colors' => array() ), - 'light' => (object) array( 'name' => 'Light', 'url' => '', 'colors' => array(), 'icon_colors' => array() ), - 'modern' => (object) array( 'name' => 'Modern', 'url' => '', 'colors' => array(), 'icon_colors' => array() ), - 'coffee' => (object) array( 'name' => 'Coffee', 'url' => '', 'colors' => array(), 'icon_colors' => array() ), + 'ocean' => (object) array( + 'name' => 'Ocean', + 'url' => '', + 'colors' => array(), + 'icon_colors' => array(), + ), + 'fresh' => (object) array( + 'name' => 'Default', + 'url' => '', + 'colors' => array(), + 'icon_colors' => array(), + ), + 'light' => (object) array( + 'name' => 'Light', + 'url' => '', + 'colors' => array(), + 'icon_colors' => array(), + ), + 'modern' => (object) array( + 'name' => 'Modern', + 'url' => '', + 'colors' => array(), + 'icon_colors' => array(), + ), + 'coffee' => (object) array( + 'name' => 'Coffee', + 'url' => '', + 'colors' => array(), + 'icon_colors' => array(), + ), ); $user_id = self::factory()->user->create( array( 'role' => 'subscriber' ) ); From db35b01b5ac3f56afa0d6aebafd815735eedb20e Mon Sep 17 00:00:00 2001 From: Paul Bearne Date: Wed, 6 May 2026 16:45:03 -0400 Subject: [PATCH 3/4] Fix formatting of color scheme properties --- .../includes/misc/adminColorSchemePicker.php | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php b/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php index 438c2d06050fc..9ae6cda41572e 100644 --- a/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php +++ b/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php @@ -39,8 +39,8 @@ public function test_admin_color_scheme_picker_default_selection() { 'url' => 'fresh.css', 'colors' => array( '#1d2327', '#2c3338', '#2271b1', '#72aee6' ), 'icon_colors' => array( - 'base' => '#a7aaad', - 'focus' => '#72aee6', + 'base' => '#a7aaad', + 'focus' => '#72aee6', 'current' => '#fff', ), ), @@ -49,8 +49,8 @@ public function test_admin_color_scheme_picker_default_selection() { 'url' => 'modern.css', 'colors' => array( '#1e1e1e', '#383838', '#007cba', '#e0e0e0' ), 'icon_colors' => array( - 'base' => '#f0f0f1', - 'focus' => '#fff', + 'base' => '#f0f0f1', + 'focus' => '#fff', 'current' => '#fff', ), ), @@ -153,33 +153,33 @@ public function test_admin_color_scheme_picker_sorting() { $_wp_admin_css_colors = array( 'ocean' => (object) array( - 'name' => 'Ocean', - 'url' => '', - 'colors' => array(), + 'name' => 'Ocean', + 'url' => '', + 'colors' => array(), 'icon_colors' => array(), ), 'fresh' => (object) array( - 'name' => 'Default', - 'url' => '', - 'colors' => array(), + 'name' => 'Default', + 'url' => '', + 'colors' => array(), 'icon_colors' => array(), ), 'light' => (object) array( - 'name' => 'Light', - 'url' => '', - 'colors' => array(), + 'name' => 'Light', + 'url' => '', + 'colors' => array(), 'icon_colors' => array(), ), 'modern' => (object) array( - 'name' => 'Modern', - 'url' => '', - 'colors' => array(), + 'name' => 'Modern', + 'url' => '', + 'colors' => array(), 'icon_colors' => array(), ), 'coffee' => (object) array( - 'name' => 'Coffee', - 'url' => '', - 'colors' => array(), + 'name' => 'Coffee', + 'url' => '', + 'colors' => array(), 'icon_colors' => array(), ), ); From 4d65985d7b525ab97638a8390e4359a3e4534781 Mon Sep 17 00:00:00 2001 From: Paul Bearne Date: Wed, 6 May 2026 16:47:28 -0400 Subject: [PATCH 4/4] Fix formatting of input elements retrieval --- .../tests/admin/includes/misc/adminColorSchemePicker.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php b/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php index 9ae6cda41572e..c3aa4d9658a65 100644 --- a/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php +++ b/tests/phpunit/tests/admin/includes/misc/adminColorSchemePicker.php @@ -200,7 +200,7 @@ public function test_admin_color_scheme_picker_sorting() { $dom->loadHTML( $output ); libxml_clear_errors(); - $inputs = $dom->getElementsByTagName( 'input' ); + $inputs = $dom->getElementsByTagName( 'input' ); $found_colors = array(); foreach ( $inputs as $input ) { if ( 'radio' === $input->getAttribute( 'type' ) ) {