summaryrefslogtreecommitdiffstats
path: root/toolkit/components/aboutconfig/test/browser/browser_search.js
blob: 89a0c0c8668f147118c5d4b2c21f7ff578cbf72c (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
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

add_setup(async function () {
  await SpecialPowers.pushPrefEnv({
    set: [
      ["test.aboutconfig.a", "test value 1"],
      ["test.aboutconfig.ab", "test value 2"],
      ["test.aboutconfig.bc", "test value 3"],
    ],
  });
});

add_task(async function test_search() {
  await AboutConfigTest.withNewTab(async function () {
    await this.document.l10n.translateFragment(this.document.documentElement);
    let prefArray = Services.prefs.getChildList("");

    // The total number of preferences may change at any time because of
    // operations running in the background, so we only test approximately.
    // The change in count would be because of one or two added preferences,
    // but we tolerate a difference of up to 50 preferences just to be safe.
    // We want thousands of prefs instead of a few dozen that are filtered.
    Assert.greater(this.rows.length, prefArray.length - 50);

    // Filter a subset of preferences. The "browser.download." branch is
    // chosen because it is very unlikely that its preferences would be
    // modified by other code during the execution of this test.
    this.search("Wser.down   ");

    let filteredPrefArray = prefArray.filter(pref =>
      pref.includes("wser.down")
    );
    // Adding +1 to the list since button does not match an exact
    // preference name then a row is added for the user to add a
    // new button preference if desired
    Assert.equal(this.rows.length, filteredPrefArray.length + 1);

    // Show all preferences again after filtering.
    this.showAll();
    Assert.equal(this.searchInput.value, "");

    // The total number of preferences may change at any time because of
    // operations running in the background, so we only test approximately.
    // The change in count would be because of one or two added preferences,
    // but we tolerate a difference of up to 50 preferences just to be safe.
    // We want thousands of prefs instead of a few dozen that are filtered.
    Assert.greater(this.rows.length, prefArray.length - 50);

    // Check if "Only show modified" feature works.
    EventUtils.sendMouseEvent({ type: "click" }, this.showOnlyModifiedCheckbox);
    Assert.ok(this.rows.every(r => r.hasClass("has-user-value")));

    // Uncheck checkbox
    EventUtils.sendMouseEvent({ type: "click" }, this.showOnlyModifiedCheckbox);
    Assert.ok(!this.rows.every(r => r.hasClass("has-user-value")));

    // Pressing ESC while showing all preferences returns to the initial page.
    EventUtils.sendKey("escape");
    Assert.equal(this.rows.length, 0);

    // Test invalid search returns no preferences.
    // Expecting 1 row to be returned since it offers the ability to add.
    this.search("aJunkValueasdf");
    Assert.equal(this.rows.length, 1);
    // The has-visible-prefs attribute is used to style the border of the add row.
    Assert.ok(!this.prefsTable.hasAttribute("has-visible-prefs"));
    let addRow = this.getRow("aJunkValueasdf");
    Assert.equal(getComputedStyle(addRow.valueCell)["border-top-width"], "0px");

    // Pressing ESC clears the field and returns to the initial page.
    EventUtils.sendKey("escape");
    Assert.equal(this.searchInput.value, "");
    Assert.equal(this.rows.length, 0);

    // Two preferences match this filter, and one of those matches exactly.
    this.search("test.aboutconfig.a");
    Assert.equal(this.rows.length, 2);

    // When searching case insensitively, there is an additional row to add a
    // new preference with the same name but a different case.
    this.search("TEST.aboutconfig.a");
    Assert.equal(this.rows.length, 3);
    // The has-visible-prefs attribute is used to style the border of the add row.
    Assert.ok(this.prefsTable.hasAttribute("has-visible-prefs"));
    addRow = this.getRow("TEST.aboutconfig.a");
    Assert.equal(getComputedStyle(addRow.valueCell)["border-top-width"], "1px");

    // Entering an empty string returns to the initial page.
    this.search("");
    Assert.equal(this.rows.length, 0);
    Assert.ok(!this.prefsTable.hasAttribute("has-visible-prefs"));
  });
});

add_task(async function test_search_wildcard() {
  await AboutConfigTest.withNewTab(async function () {
    const extra = 1; // "Add" row

    // A trailing wildcard
    this.search("test.about*");
    Assert.equal(this.rows.length, 3 + extra);

    // A wildcard in middle
    this.search("test.about*a");
    Assert.equal(this.rows.length, 2 + extra);
    this.search("test.about*ab");
    Assert.equal(this.rows.length, 1 + extra);
    this.search("test.aboutcon*fig");
    Assert.equal(this.rows.length, 3 + extra);

    // Multiple wildcards in middle
    this.search("test.about*fig*ab");
    Assert.equal(this.rows.length, 1 + extra);
    this.search("test.about*config*ab");
    Assert.equal(this.rows.length, 1 + extra);
  });
});

add_task(async function test_search_delayed() {
  await AboutConfigTest.withNewTab(async function () {
    // Start with the initial empty page.
    this.search("");

    // We need to wait more than the search typing timeout to make sure that
    // nothing happens when entering a short string.
    EventUtils.synthesizeKey("t");
    EventUtils.synthesizeKey("e");
    // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
    await new Promise(resolve => setTimeout(resolve, 500));
    Assert.equal(this.rows.length, 0);

    // Pressing Enter will force a search to occur anyways.
    EventUtils.sendKey("return");
    Assert.greater(this.rows.length, 0);

    // Prepare the table and the search field for the next test.
    this.search("test.aboutconfig.a");
    Assert.equal(this.rows.length, 2);

    // The table is updated in a single microtask, so we don't need to wait for
    // specific mutations, we can just continue when any of the children or
    // their "hidden" attributes are updated.
    let prefsTableChanged = new Promise(resolve => {
      let observer = new MutationObserver(() => {
        observer.disconnect();
        resolve();
      });
      observer.observe(this.prefsTable, { childList: true });
      for (let element of this.prefsTable.children) {
        observer.observe(element, { attributes: true });
      }
    });

    // Add a character and test that the table is not updated immediately.
    EventUtils.synthesizeKey("b");
    Assert.equal(this.rows.length, 2);

    // The table will eventually be updated after a delay.
    await prefsTableChanged;
    Assert.equal(this.rows.length, 1);
  });
});

add_task(async function test_search_add_row_color() {
  await AboutConfigTest.withNewTab(async function () {
    // When the row is the only one displayed, it doesn't have the "odd" class.
    this.search("test.aboutconfig.add");
    Assert.equal(this.rows.length, 1);
    Assert.ok(!this.getRow("test.aboutconfig.add").hasClass("odd"));

    // When displayed with one other preference, the "odd" class is present.
    this.search("test.aboutconfig.b");
    Assert.equal(this.rows.length, 2);
    Assert.ok(this.getRow("test.aboutconfig.b").hasClass("odd"));
  });
});