Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

"use strict";
/**
* This file contains tests for the Preferences search bar.
*/
/**
* Test that we only search the selected child of a XUL deck.
* When we search "Remove Account",
* it should not show the "Remove Account" button if the Firefox account is not logged in yet.
*/
add_task(async function () {
await openPreferencesViaOpenPreferencesAPI("paneSync", { leaveOpen: true });
let weavePrefsDeck =
gBrowser.contentDocument.getElementById("weavePrefsDeck");
is(
weavePrefsDeck.selectedIndex,
0,
"Should select the #noFxaAccount child node"
);
// Performs search.
let searchInput = gBrowser.contentDocument.getElementById("searchInput");
is(
searchInput,
gBrowser.contentDocument.activeElement.closest("#searchInput"),
"Search input should be focused when visiting preferences"
);
let query = "Sync";
let searchCompletedPromise = BrowserTestUtils.waitForEvent(
gBrowser.contentWindow,
"PreferencesSearchCompleted",
evt => evt.detail == query
);
EventUtils.sendString(query);
await searchCompletedPromise;
let mainPrefTag = gBrowser.contentDocument.getElementById("mainPrefPane");
for (let i = 0; i < mainPrefTag.childElementCount; i++) {
let child = mainPrefTag.children[i];
if (child.id == "header-searchResults" || child.id == "weavePrefsDeck") {
is_element_visible(child, "Should be in search results");
} else if (child.id) {
is_element_hidden(child, "Should not be in search results");
}
}
// Ensure the "Remove Account" button exists in the hidden child of the <xul:deck>.
let unlinkFxaAccount = weavePrefsDeck.children[1].querySelector(
"#unverifiedUnlinkFxaAccount"
);
is(
unlinkFxaAccount.label,
"Remove Account",
"The Remove Account button should exist"
);
// Performs search.
searchInput.focus();
query = "Remove Account";
searchCompletedPromise = BrowserTestUtils.waitForEvent(
gBrowser.contentWindow,
"PreferencesSearchCompleted",
evt => evt.detail == query
);
EventUtils.sendString(query);
await searchCompletedPromise;
let noResultsEl = gBrowser.contentDocument.querySelector(
"#no-results-message"
);
is_element_visible(noResultsEl, "Should be reporting no results");
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
/**
* Test that we search using `search-l10n-ids`.
*
* The test uses element `showUpdateHistory` and
* l10n id `language-and-appearance-header` and expects the element
* to be matched on the first word from the l10n id value ("Language" in en-US).
*/
add_task(async function () {
let l10nId = "language-and-appearance-header";
await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
leaveOpen: true,
});
// First, lets make sure that the element is not matched without
// `search-l10n-ids`.
{
let searchInput = gBrowser.contentDocument.getElementById("searchInput");
let suhElem = gBrowser.contentDocument.getElementById("showUpdateHistory");
is(
searchInput,
gBrowser.contentDocument.activeElement.closest("#searchInput"),
"Search input should be focused when visiting preferences"
);
ok(
!suhElem.getAttribute("search-l10n-ids").includes(l10nId),
"showUpdateHistory element should not contain the l10n id here."
);
let query = "Language";
let searchCompletedPromise = BrowserTestUtils.waitForEvent(
gBrowser.contentWindow,
"PreferencesSearchCompleted",
evt => evt.detail == query
);
EventUtils.sendString(query);
await searchCompletedPromise;
is_element_hidden(
suhElem,
"showUpdateHistory should not be in search results"
);
}
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
// Now, let's add the l10n id to the element and perform the same search again.
await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
leaveOpen: true,
});
{
let searchInput = gBrowser.contentDocument.getElementById("searchInput");
is(
searchInput,
gBrowser.contentDocument.activeElement.closest("#searchInput"),
"Search input should be focused when visiting preferences"
);
let suhElem = gBrowser.contentDocument.getElementById("showUpdateHistory");
suhElem.setAttribute("search-l10n-ids", l10nId);
let query = "Language";
let searchCompletedPromise = BrowserTestUtils.waitForEvent(
gBrowser.contentWindow,
"PreferencesSearchCompleted",
evt => evt.detail == query
);
EventUtils.sendString(query);
await searchCompletedPromise;
if (
AppConstants.platform === "win" &&
Services.sysinfo.getProperty("hasWinPackageId")
) {
is_element_hidden(
suhElem,
"showUpdateHistory should not be in search results"
);
} else {
is_element_visible(
suhElem,
"showUpdateHistory should be in search results"
);
}
}
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
/**
* Test that search works as expected for custom elements that utilize both
* slots and shadow DOM. We should be able to find text the shadow DOM.
*/
add_task(async function testSearchShadowDOM() {
await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
leaveOpen: true,
});
// Create the toggle.
let { mozElements, SHADOW_DOM_TEXT } = createMozCustomElements(gBrowser);
mozElements.forEach(el => {
ok(
!BrowserTestUtils.isVisible(el),
`${el.localName} is not visible prior to search.`
);
});
// Perform search with text found in moz-toggle's shadow DOM.
let query = SHADOW_DOM_TEXT;
let searchCompletedPromise = BrowserTestUtils.waitForEvent(
gBrowser.contentWindow,
"PreferencesSearchCompleted",
evt => evt.detail == query
);
EventUtils.sendString(query);
await searchCompletedPromise;
mozElements.forEach(el => {
ok(
BrowserTestUtils.isVisible(el),
`${el.localName} is visible after searching for string in the shadow DOM.`
);
});
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
/**
* Test that search works as expected for custom elements that utilize both
* slots and shadow DOM. We should be able to find text the light DOM.
*/
add_task(async function testSearchLightDOM() {
await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
leaveOpen: true,
});
// Create the toggle.
let { mozElements, LIGHT_DOM_TEXT } = createMozCustomElements(gBrowser, [
"moz-toggle",
]);
let toggle = mozElements[0];
// Perform search with text found in moz-toggle's slotted content.
let query = LIGHT_DOM_TEXT;
let searchCompletedPromise = BrowserTestUtils.waitForEvent(
gBrowser.contentWindow,
"PreferencesSearchCompleted",
evt => evt.detail == query
);
EventUtils.sendString(query);
await searchCompletedPromise;
ok(
BrowserTestUtils.isVisible(toggle),
"Toggle is visible again after searching for text found in slotted content."
);
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
const MOZ_CUSTOM_ELEMENTS = [
"moz-toggle",
"moz-radio-group",
"moz-radio",
"moz-checkbox",
];
// Create multiple moz- custom elements with the same label.
function createMozCustomElements(gBrowser, elements = MOZ_CUSTOM_ELEMENTS) {
const SHADOW_DOM_TEXT = "This text lives in the shadow DOM";
const LIGHT_DOM_TEXT = "This text lives in the light DOM";
let doc = gBrowser.contentDocument;
let mozElements = elements.map(tag => {
let el = doc.createElement(tag);
el.label = SHADOW_DOM_TEXT;
return el;
});
let [toggle, radioGroup, radioButton, ...rest] = mozElements;
let protectionsGroup = doc.getElementById("trackingGroup");
if (toggle) {
let link = doc.createElement("a");
link.href = "https://mozilla.org/";
link.textContent = LIGHT_DOM_TEXT;
toggle.append(link);
link.slot = "support-link";
protectionsGroup.append(toggle);
}
if (radioGroup && radioButton) {
radioGroup.appendChild(radioButton);
protectionsGroup.append(radioGroup);
}
protectionsGroup.append(...rest);
return { SHADOW_DOM_TEXT, LIGHT_DOM_TEXT, mozElements };
}