From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../test/forms/browser_selectpopup_colors.js | 867 +++++++++++++++++++++ 1 file changed, 867 insertions(+) create mode 100644 browser/base/content/test/forms/browser_selectpopup_colors.js (limited to 'browser/base/content/test/forms/browser_selectpopup_colors.js') diff --git a/browser/base/content/test/forms/browser_selectpopup_colors.js b/browser/base/content/test/forms/browser_selectpopup_colors.js new file mode 100644 index 0000000000..00b399c672 --- /dev/null +++ b/browser/base/content/test/forms/browser_selectpopup_colors.js @@ -0,0 +1,867 @@ +const gSelects = { + PAGECONTENT_COLORS: + "" + + "", + + PAGECONTENT_COLORS_ON_SELECT: + "" + + "", + + TRANSPARENT_SELECT: + "" + + "", + + OPTION_COLOR_EQUAL_TO_UABACKGROUND_COLOR_SELECT: + "" + + "", + + GENERIC_OPTION_STYLED_AS_IMPORTANT: + "" + + "", + + TRANSLUCENT_SELECT_BECOMES_OPAQUE: + "" + + "", + + TRANSLUCENT_SELECT_APPLIES_ON_BASE_COLOR: + "" + + "", + + DISABLED_OPTGROUP_AND_OPTIONS: + "" + + "", + + SELECT_CHANGES_COLOR_ON_FOCUS: + "" + + "", + + SELECT_BGCOLOR_ON_SELECT_COLOR_ON_OPTIONS: + "" + + "", + + SELECT_STYLE_OF_OPTION_IS_BASED_ON_FOCUS_OF_SELECT: + "" + + "", + + SELECT_STYLE_OF_OPTION_CHANGES_AFTER_FOCUS_EVENT: + "" + + " var select = document.getElementById('one');" + + " select.addEventListener('focus', () => select.style.color = 'red');" + + "", + + SELECT_COLOR_OF_OPTION_CHANGES_AFTER_TRANSITIONEND: + "", + + SELECT_TEXTSHADOW_OF_OPTION_CHANGES_AFTER_TRANSITIONEND: + "", + + SELECT_TRANSPARENT_COLOR_WITH_TEXT_SHADOW: + "", + + SELECT_LONG_WITH_TRANSITION: + ""; + return rv; + })(), + + SELECT_INHERITED_COLORS_ON_OPTIONS_DONT_GET_UNIQUE_RULES_IF_RULE_SET_ON_SELECT: ` + +`, + + SELECT_FONT_INHERITS_TO_OPTION: ` + +`, + + SELECT_SCROLLBAR_PROPS: ` + +`, + DEFAULT_DARKMODE: ` + +`, + + DEFAULT_DARKMODE_DARK: ` + + +`, + + SPLIT_FG_BG_OPTION_DARKMODE: ` + +`, + + IDENTICAL_BG_DIFF_FG_OPTION_DARKMODE: ` + +`, +}; + +function rgbaToString(parsedColor) { + let { r, g, b, a } = parsedColor; + if (a == 1) { + return `rgb(${r}, ${g}, ${b})`; + } + return `rgba(${r}, ${g}, ${b}, ${a})`; +} + +function testOptionColors(test, index, item, menulist) { + // The label contains a JSON string of the expected colors for + // `color` and `background-color`. + let expected = JSON.parse(item.label); + + // Press Down to move the selected item to the next item in the + // list and check the colors of this item when it's not selected. + EventUtils.synthesizeKey("KEY_ArrowDown"); + + if (expected.end) { + return; + } + + if (expected.unstyled) { + ok( + !item.hasAttribute("customoptionstyling"), + `${test}: Item ${index} should not have any custom option styling: ${item.outerHTML}` + ); + } else { + is( + getComputedStyle(item).color, + expected.color, + `${test}: Item ${index} has correct foreground color` + ); + is( + getComputedStyle(item).backgroundColor, + expected.backgroundColor, + `${test}: Item ${index} has correct background color` + ); + if (expected.textShadow) { + is( + getComputedStyle(item).textShadow, + expected.textShadow, + `${test}: Item ${index} has correct text-shadow color` + ); + } + } +} + +function computeLabels(tab) { + return SpecialPowers.spawn(tab.linkedBrowser, [], function () { + function _rgbaToString(parsedColor) { + let { r, g, b, a } = parsedColor; + if (a == 1) { + return `rgb(${r}, ${g}, ${b})`; + } + return `rgba(${r}, ${g}, ${b}, ${a})`; + } + function computeColors(expected) { + let any = false; + for (let color of Object.keys(expected)) { + if ( + color != "colorScheme" && + color.toLowerCase().includes("color") && + !expected[color].startsWith("rgb") + ) { + any = true; + expected[color] = _rgbaToString( + InspectorUtils.colorToRGBA(expected[color], content.document) + ); + } + } + return any; + } + for (let option of content.document.querySelectorAll("option,optgroup")) { + if (!option.label) { + continue; + } + let expected; + try { + expected = JSON.parse(option.label); + } catch (ex) { + continue; + } + if (computeColors(expected)) { + option.label = JSON.stringify(expected); + } + } + }); +} + +async function openSelectPopup(select) { + const pageUrl = "data:text/html," + escape(select); + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl); + + await computeLabels(tab); + + let popupShownPromise = BrowserTestUtils.waitForSelectPopupShown(window); + await BrowserTestUtils.synthesizeMouseAtCenter( + "#one", + { type: "mousedown" }, + gBrowser.selectedBrowser + ); + let selectPopup = await popupShownPromise; + let menulist = selectPopup.parentNode; + return { tab, menulist, selectPopup }; +} + +async function testSelectColors(selectID, itemCount, options) { + let select = gSelects[selectID]; + let { tab, menulist, selectPopup } = await openSelectPopup(select); + if (options.unstyled) { + ok( + !selectPopup.hasAttribute("customoptionstyling"), + `Shouldn't have custom option styling for ${selectID}` + ); + } + let arrowSB = selectPopup.shadowRoot.querySelector( + ".menupopup-arrowscrollbox" + ); + if (options.waitForComputedStyle) { + let property = options.waitForComputedStyle.property; + let expectedValue = options.waitForComputedStyle.value; + await TestUtils.waitForCondition(() => { + let node = ["background-image", "background-color"].includes(property) + ? arrowSB + : selectPopup; + let value = getComputedStyle(node).getPropertyValue(property); + info(`<${node.localName}> has ${property}: ${value}`); + return value == expectedValue; + }, `${selectID} - Waiting for `, + function (browser) { + return SpecialPowers.spawn(browser, [], function () { + let cs = content.getComputedStyle( + content.document.querySelector("select") + ); + return { + backgroundColor: cs.backgroundColor, + }; + }); + } + ); +}); + +// This test checks when a element has styles applied to itself. +add_task(async function test_colors_applied_to_popup() { + let options = { + selectColor: "rgb(255, 255, 255)", + selectBgColor: "rgb(126, 58, 58)", + }; + await testSelectColors("PAGECONTENT_COLORS_ON_SELECT", 4, options); +}); + +// This test checks when a element has a background set, and the +// options have their own background set which is equal to the default +// user-agent background color, but should be used because the select +// background color has been changed. +add_task(async function test_options_inverted_from_select_background() { + // The popup has a black background and white text, but the + // options inside of it have flipped the colors. + let options = { + selectColor: "rgb(255, 255, 255)", + selectBgColor: "rgb(0, 0, 0)", + }; + await testSelectColors( + "OPTION_COLOR_EQUAL_TO_UABACKGROUND_COLOR_SELECT", + 2, + options + ); +}); + +// This test checks when a element has a background set, and the +// options have their own background set which is equal to the default +// user-agent background color, but should be used because the select +// background color has been changed. +add_task(async function test_translucent_select_becomes_opaque() { + // The popup is requested to show a translucent background + // but we apply the requested background color on the system's base color. + let options = { + selectColor: "rgb(0, 0, 0)", + selectBgColor: "rgb(255, 255, 255)", + }; + await testSelectColors("TRANSLUCENT_SELECT_BECOMES_OPAQUE", 2, options); +}); + +// This test checks when a popup has a translucent background color, +// and that the color painted to the screen of the translucent background +// matches what the user expects. +add_task(async function test_translucent_select_applies_on_base_color() { + // The popup is requested to show a translucent background + // but we apply the requested background color on the system's base color. + let options = { + selectColor: "rgb(0, 0, 0)", + selectBgColor: "rgb(255, 115, 115)", + }; + await testSelectColors( + "TRANSLUCENT_SELECT_APPLIES_ON_BASE_COLOR", + 2, + options + ); +}); + +add_task(async function test_disabled_optgroup_and_options() { + await testSelectColors("DISABLED_OPTGROUP_AND_OPTIONS", 17, { + skipSelectColorTest: true, + }); +}); + +add_task(async function test_disabled_optgroup_and_options() { + let options = { + selectColor: "rgb(0, 0, 0)", + selectBgColor: "rgb(255, 165, 0)", + }; + + await testSelectColors("SELECT_CHANGES_COLOR_ON_FOCUS", 2, options); +}); + +add_task(async function test_bgcolor_on_select_color_on_options() { + let options = { + selectColor: "rgb(0, 0, 0)", + selectBgColor: "rgb(0, 0, 0)", + }; + + await testSelectColors( + "SELECT_BGCOLOR_ON_SELECT_COLOR_ON_OPTIONS", + 2, + options + ); +}); + +add_task( + async function test_style_of_options_is_dependent_on_focus_of_select() { + let options = { + selectColor: "rgb(0, 0, 0)", + selectBgColor: "rgb(58, 150, 221)", + }; + + await testSelectColors( + "SELECT_STYLE_OF_OPTION_IS_BASED_ON_FOCUS_OF_SELECT", + 2, + options + ); + } +); + +add_task( + async function test_style_of_options_is_dependent_on_focus_of_select_after_event() { + let options = { + skipSelectColorTest: true, + waitForComputedStyle: { + property: "--panel-color", + value: "rgb(255, 0, 0)", + }, + }; + await testSelectColors( + "SELECT_STYLE_OF_OPTION_CHANGES_AFTER_FOCUS_EVENT", + 2, + options + ); + } +); + +add_task(async function test_color_of_options_is_dependent_on_transitionend() { + let options = { + selectColor: "rgb(0, 0, 0)", + selectBgColor: "rgb(255, 165, 0)", + waitForComputedStyle: { + property: "background-image", + value: "linear-gradient(rgb(255, 165, 0), rgb(255, 165, 0))", + }, + }; + + await testSelectColors( + "SELECT_COLOR_OF_OPTION_CHANGES_AFTER_TRANSITIONEND", + 2, + options + ); +}); + +add_task( + async function test_textshadow_of_options_is_dependent_on_transitionend() { + let options = { + skipSelectColorTest: true, + waitForComputedStyle: { + property: "text-shadow", + value: "rgb(48, 48, 48) 0px 0px 0px", + }, + }; + + await testSelectColors( + "SELECT_TEXTSHADOW_OF_OPTION_CHANGES_AFTER_TRANSITIONEND", + 2, + options + ); + } +); + +add_task(async function test_transparent_color_with_text_shadow() { + let options = { + selectColor: "rgba(0, 0, 0, 0)", + selectTextShadow: "rgb(48, 48, 48) 0px 0px 0px", + selectBgColor: kDefaultSelectStyles.backgroundColor, + }; + + await testSelectColors( + "SELECT_TRANSPARENT_COLOR_WITH_TEXT_SHADOW", + 2, + options + ); +}); + +add_task( + async function test_select_with_transition_doesnt_lose_scroll_position() { + let options = { + selectColor: "rgb(128, 0, 128)", + selectBgColor: kDefaultSelectStyles.backgroundColor, + waitForComputedStyle: { + property: "--panel-color", + value: "rgb(128, 0, 128)", + }, + leaveOpen: true, + }; + + await testSelectColors("SELECT_LONG_WITH_TRANSITION", 76, options); + + let selectPopup = document.getElementById( + "ContentSelectDropdown" + ).menupopup; + let scrollBox = selectPopup.scrollBox; + is( + scrollBox.scrollTop, + scrollBox.scrollTopMax, + "The popup should be scrolled to the bottom of the list (where the selected item is)" + ); + + await hideSelectPopup("escape"); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } +); + +add_task( + async function test_select_inherited_colors_on_options_dont_get_unique_rules_if_rule_set_on_select() { + let options = { + selectColor: "rgb(0, 0, 255)", + selectTextShadow: "rgb(0, 0, 255) 1px 1px 2px", + selectBgColor: kDefaultSelectStyles.backgroundColor, + leaveOpen: true, + }; + + await testSelectColors( + "SELECT_INHERITED_COLORS_ON_OPTIONS_DONT_GET_UNIQUE_RULES_IF_RULE_SET_ON_SELECT", + 6, + options + ); + + let stylesheetEl = document.getElementById( + "ContentSelectDropdownStylesheet" + ); + + let sheet = stylesheetEl.sheet; + /* Check that the rules are what we expect: There are three different option styles (even though there are 6 options, plus the select rules). */ + let expectedSelectors = [ + "#ContentSelectDropdown .ContentSelectDropdown-item-0", + "#ContentSelectDropdown .ContentSelectDropdown-item-1", + '#ContentSelectDropdown .ContentSelectDropdown-item-1:not([_moz-menuactive="true"])', + "#ContentSelectDropdown .ContentSelectDropdown-item-2", + '#ContentSelectDropdown .ContentSelectDropdown-item-2:not([_moz-menuactive="true"])', + '#ContentSelectDropdown > menupopup > :is(menuitem, menucaption):not([_moz-menuactive="true"])', + '#ContentSelectDropdown > menupopup > :is(menuitem, menucaption)[_moz-menuactive="true"]', + ].sort(); + + let actualSelectors = [...sheet.cssRules].map(r => r.selectorText).sort(); + is( + actualSelectors.length, + expectedSelectors.length, + "Should have the expected number of rules" + ); + for (let i = 0; i < expectedSelectors.length; ++i) { + is( + actualSelectors[i], + expectedSelectors[i], + `Selector ${i} should match` + ); + } + + await hideSelectPopup("escape"); + BrowserTestUtils.removeTab(gBrowser.selectedTab); + } +); + +add_task(async function test_select_font_inherits_to_option() { + let { tab, menulist, selectPopup } = await openSelectPopup( + gSelects.SELECT_FONT_INHERITS_TO_OPTION + ); + + let popupFont = getComputedStyle(selectPopup).fontFamily; + let items = menulist.querySelectorAll("menuitem"); + is(items.length, 2, "Should have two options"); + let firstItemFont = getComputedStyle(items[0]).fontFamily; + let secondItemFont = getComputedStyle(items[1]).fontFamily; + + is( + popupFont, + firstItemFont, + "First menuitem's font should be inherited from the select" + ); + isnot( + popupFont, + secondItemFont, + "Second menuitem's font should be the author specified one" + ); + + await hideSelectPopup("escape"); + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function test_scrollbar_props() { + let { tab, selectPopup } = await openSelectPopup( + gSelects.SELECT_SCROLLBAR_PROPS + ); + + let popupStyle = getComputedStyle(selectPopup); + is(popupStyle.getPropertyValue("--content-select-scrollbar-width"), "thin"); + is(popupStyle.scrollbarColor, "rgb(255, 0, 0) rgb(0, 0, 255)"); + + let scrollBoxStyle = getComputedStyle(selectPopup.scrollBox.scrollbox); + is(scrollBoxStyle.overflow, "auto", "Should be the scrollable box"); + is(scrollBoxStyle.scrollbarWidth, "thin"); + is(scrollBoxStyle.scrollbarColor, "rgb(255, 0, 0) rgb(0, 0, 255)"); + + await hideSelectPopup("escape"); + BrowserTestUtils.removeTab(tab); +}); + +if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) { + add_task(async function test_darkmode() { + let lightSelectColor = rgbaToString( + InspectorUtils.colorToRGBA("MenuText", document) + ); + let lightSelectBgColor = rgbaToString( + InspectorUtils.colorToRGBA("Menu", document) + ); + + // Force dark mode: + let darkModeQuery = matchMedia("(prefers-color-scheme: dark)"); + let darkModeChange = BrowserTestUtils.waitForEvent(darkModeQuery, "change"); + await SpecialPowers.pushPrefEnv({ set: [["ui.systemUsesDarkTheme", 1]] }); + await darkModeChange; + + // Determine colours from the main context menu: + let darkSelectColor = rgbaToString( + InspectorUtils.colorToRGBA("MenuText", document) + ); + let darkSelectBgColor = rgbaToString( + InspectorUtils.colorToRGBA("Menu", document) + ); + + isnot(lightSelectColor, darkSelectColor); + isnot(lightSelectBgColor, darkSelectBgColor); + + let { tab } = await openSelectPopup(gSelects.DEFAULT_DARKMODE); + + await testSelectColors("DEFAULT_DARKMODE", 3, { + selectColor: lightSelectColor, + selectBgColor: lightSelectBgColor, + }); + + await hideSelectPopup("escape"); + + await testSelectColors("DEFAULT_DARKMODE_DARK", 3, { + selectColor: darkSelectColor, + selectBgColor: darkSelectBgColor, + }); + + await hideSelectPopup("escape"); + BrowserTestUtils.removeTab(tab); + + ({ tab } = await openSelectPopup( + gSelects.IDENTICAL_BG_DIFF_FG_OPTION_DARKMODE + )); + + // Custom styling on the options enforces using the select styling, too, + // even if it matched the UA style. They'll be overridden on individual + // options where necessary. + await testSelectColors("IDENTICAL_BG_DIFF_FG_OPTION_DARKMODE", 3, { + selectColor: "rgb(0, 0, 0)", + selectBgColor: "rgb(255, 255, 255)", + }); + + await hideSelectPopup("escape"); + BrowserTestUtils.removeTab(tab); + + ({ tab } = await openSelectPopup(gSelects.SPLIT_FG_BG_OPTION_DARKMODE)); + + // Like the previous case, but here the bg colour is defined on the + // select, and the fg colour on the option. The behaviour should be the + // same. + await testSelectColors("SPLIT_FG_BG_OPTION_DARKMODE", 3, { + selectColor: "rgb(0, 0, 0)", + selectBgColor: "rgb(255, 255, 255)", + }); + + await hideSelectPopup("escape"); + BrowserTestUtils.removeTab(tab); + }); +} -- cgit v1.2.3