Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'linux' && os_version == '18.04' && asan OR os == 'linux' && os_version == '18.04' && tsan OR win11_2009 && asan
- Manifest: browser/components/preferences/tests/browser.toml
/* Any copyright is dedicated to the Public Domain.
async function launchPreferences() {
let prefs = await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
leaveOpen: true,
});
Assert.equal(prefs.selectedPane, "paneGeneral", "General pane was selected");
}
async function reset() {
// We have to add this in because the initial state of `document_color_use`
// affects the initial state of color preferenced which can change the
// starting color values.
Services.prefs.clearUserPref("browser.anchor_color");
Services.prefs.clearUserPref("browser.visited_color");
Services.prefs.clearUserPref("browser.display.foreground_color");
Services.prefs.clearUserPref("browser.display.background_color");
}
add_setup(async function () {
info("Setting the test up");
// Ensure default color values are used:
reset();
// Ensure the pref is set to "Always" on all platforms (1 is default on Mac,
// but on Windows and Linux it's 0, and the colors dialog is available on 2):
Services.prefs.setIntPref("browser.display.document_color_use", 1);
registerCleanupFunction(async function () {
reset();
Services.prefs.clearUserPref("browser.display.document_color_use");
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
});
add_task(async function testColorPicker() {
await launchPreferences();
const button = gBrowser.contentDocument.getElementById("colors");
const radiogroup = content.document.getElementById("contrastControlSettings");
const radioOff = content.document.getElementById("contrastSettingsOff");
const radioCustom = content.document.getElementById("contrastSettingsOn");
// Focus "Off" Contrast radio button:
radiogroup.focus();
Assert.equal(
radiogroup,
gBrowser.contentDocument.activeElement,
"Radio group for Custom Colors is focused"
);
Assert.equal(
radioOff,
radiogroup.querySelector("radio[focused='true']"),
"Radio group with option 'Off' is focused"
);
Assert.ok(button.disabled, "Manage Colors button is disabled");
// Focus "Custom" Contrast radio button:
EventUtils.synthesizeKey("KEY_ArrowDown");
Assert.equal(
radioCustom,
radiogroup.querySelector("radio[focused='true']"),
"Radio group with option 'Custom' is focused"
);
Assert.ok(!button.disabled, "Manage Colors button is now enabled");
// Focus "Manage Colors" button:
EventUtils.synthesizeKey("KEY_Tab");
Assert.equal(
button,
gBrowser.contentDocument.activeElement,
"Manage Colors button is focused"
);
info("Open Colors dialog");
// Open Colors sub-dialog:
let promiseSubDialogLoaded = promiseLoadSubDialog(
"chrome://browser/content/preferences/dialogs/colors.xhtml"
);
EventUtils.synthesizeKey(" ");
let colorsDialogWindow = await promiseSubDialogLoaded;
let colorsDialogDoc = colorsDialogWindow.document;
Assert.ok(colorsDialogDoc, "Colors dialog exists");
Assert.ok(
BrowserTestUtils.isVisible(colorsDialogDoc.getElementById("ColorsDialog")),
"Colors dialog is visible"
);
// Pickers and preferences defaults (should be the same length and order):
const pickerControlAttrs = [
"foregroundtextmenu",
"backgroundmenu",
"unvisitedlinkmenu",
"visitedlinkmenu",
];
const prefNames = [
"browser.display.foreground_color",
"browser.display.background_color",
"browser.anchor_color",
"browser.visited_color",
];
// Values of static preferences (https://searchfox.org/mozilla-central/rev/270c20e4b063d80ce71f029b4adc4ba03a12edc0/modules/libpref/init/StaticPrefList.yaml#1506-1508,1439-1441,1039-1041,2097-2099):
const colorValuesHex = ["#000000", "#FFFFFF", "#0000EE", "#551A8B"];
const colorValuesSystem = ["CanvasText", "Canvas", "LinkText", "VisitedText"];
// Checking the defaults are entered correctly:
Assert.equal(
prefNames.length,
pickerControlAttrs.length,
"prefNames and pickerControlAttrs arrays have the same length"
);
Assert.equal(
prefNames.length,
colorValuesHex.length,
"prefNames and colorValuesHex arrays have the same length"
);
Assert.equal(
prefNames.length,
colorValuesSystem.length,
"prefNames and colorValuesSystem arrays have the same length"
);
const expectedPickersMap = prefNames.map((pref, i) => ({
pref,
id: pickerControlAttrs[i],
control: pickerControlAttrs[i],
// Ensure a HEX value and a system color are interchangeable in this
// scenario, i.e. CanvasText resolves to #000000 in our default test cases:
expectedValues: [colorValuesSystem[i], colorValuesHex[i]],
}));
for (const picker of expectedPickersMap) {
// Pref:
const prefValue = Services.prefs.getStringPref(picker.pref, "");
Assert.ok(prefValue, `Preference with id="${picker.pref}" exists`);
const prefValueNormalized = prefValue.startsWith("#")
? prefValue.toUpperCase()
: prefValue;
// Picker:
const pickerEl = colorsDialogDoc.getElementById(picker.id);
Assert.ok(pickerEl, `Moz-input-color picker with id="${picker.id}" exists`);
const pickerValueNormalized = pickerEl.value.startsWith("#")
? pickerEl.value.toUpperCase()
: pickerEl.value;
info("Test markup of a color picker");
// Checking default picker attributes:
Assert.equal(
pickerEl.getAttribute("id"),
picker.id,
`Picker's "id" attribute is as expected`
);
Assert.equal(
pickerEl.getAttribute("control"),
picker.control,
`Picker's "control" attribute is as expected`
);
Assert.equal(
pickerEl.getAttribute("preference"),
picker.pref,
`Picker's "preference" attribute is as expected`
);
Assert.ok(
picker.expectedValues.includes(prefValueNormalized),
`Pref ${picker.pref} value "${prefValue}" is one of two expected values: ${picker.expectedValues.join(" or ")}`
);
Assert.ok(
picker.expectedValues.includes(pickerValueNormalized),
`Picker "${picker.id}" value "${pickerEl.value}" is one of two expected values: ${picker.expectedValues.join(" or ")}`
);
Assert.ok(
pickerEl.hasAttribute("data-l10n-id"),
`Picker has a localizable ID`
);
Assert.equal(
pickerEl.getAttribute("data-l10n-attrs"),
"label",
`Picker has a localizable "label" attribute`
);
Assert.ok(pickerEl.label, `Picker has a localizable label text`);
// Checking pref and picker values are referencing the same actual color:
const prefValueIsExpected =
picker.expectedValues.includes(prefValueNormalized);
const pickerValueIsExpected = picker.expectedValues.includes(
pickerValueNormalized
);
const valuesMatchExactly = prefValueNormalized === pickerValueNormalized;
Assert.ok(
valuesMatchExactly || (prefValueIsExpected && pickerValueIsExpected),
`Pref and picker values should be using the same color:
pref="${prefValue}", pickerEl="${pickerEl.value}", expected=
${picker.expectedValues.join(" or ")}`
);
info("Test a color picker is focusable");
// Confirming the focus location:
Assert.equal(
pickerEl,
colorsDialogDoc.activeElement,
`The ${picker.id} picker is focused`
);
// Move focus to the next picker:
EventUtils.synthesizeKey("KEY_Tab");
}
info("Close Colors dialog");
EventUtils.synthesizeKey("KEY_Enter");
// Confirm the focus is returned to the "Manage Colors" button:
Assert.equal(
button,
gBrowser.contentDocument.activeElement,
"Manage Colors button is focused"
);
});