summaryrefslogtreecommitdiffstats
path: root/browser/components/preferences/tests/browser_search_within_preferences_2.js
blob: 5fcb445adc89949a1d1644309dbe4454981d97cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
"use strict";
/**
 * This file contains tests for the Preferences search bar.
 */

/**
 * Enabling searching functionality. Will display search bar from this testcase forward.
 */
add_task(async function () {
  await SpecialPowers.pushPrefEnv({
    set: [["browser.preferences.search", true]],
  });
});

/**
 * 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 { toggle, SHADOW_DOM_TEXT } = createToggle(gBrowser);

  ok(
    !BrowserTestUtils.isVisible(toggle),
    "Toggle 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;
  ok(
    BrowserTestUtils.isVisible(toggle),
    "Toggle 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 { toggle, LIGHT_DOM_TEXT } = createToggle(gBrowser);

  // 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);
});

// Create a toggle with a slotted link element.
function createToggle(gBrowser) {
  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 toggle = doc.createElement("moz-toggle");
  toggle.label = SHADOW_DOM_TEXT;

  let link = doc.createElement("a");
  link.href = "https://mozilla.org/";
  link.textContent = LIGHT_DOM_TEXT;
  toggle.append(link);
  link.slot = "support-link";

  let protectionsGroup = doc.getElementById("trackingGroup");
  protectionsGroup.append(toggle);

  return { SHADOW_DOM_TEXT, LIGHT_DOM_TEXT, toggle };
}