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
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This test makes sure that when the view updates itself and appends new rows,
// the new rows start out hidden when they exceed the current visible result
// span count. It includes a tip result so that it tests a row with > 1 result
// span.
"use strict";
add_task(async function viewUpdateAppendHidden() {
// We'll use this test provider to test specific results. We assume that
// history and bookmarks have been cleared (by init() above).
let provider = new DelayingTestProvider();
UrlbarProvidersManager.registerProvider(provider);
registerCleanupFunction(() => {
UrlbarProvidersManager.unregisterProvider(provider);
});
// We do two searches below without closing the panel. Use "firefox cach" as
// the first query and "firefox cache" as the second so that (1) an
// intervention tip is triggered both times but also so that (2) the queries
// are different each time.
let baseQuery = "firefox cache";
let queries = [baseQuery.substring(0, baseQuery.length - 1), baseQuery];
let maxResults = UrlbarPrefs.get("maxRichResults");
let queryStrings = [];
for (let i = 0; i < maxResults; i++) {
queryStrings.push(`${baseQuery} ${i}`);
}
// First search: Trigger the intervention tip and a view full of search
// suggestions.
provider._results = queryStrings.map(
suggestion =>
new UrlbarResult(
UrlbarUtils.RESULT_TYPE.SEARCH,
UrlbarUtils.RESULT_SOURCE.SEARCH,
{
query: queries[0],
suggestion,
lowerCaseSuggestion: suggestion.toLocaleLowerCase(),
engine: Services.search.defaultEngine.name,
}
)
);
provider.finishQueryPromise = Promise.resolve();
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: queries[0],
});
// Sanity check the tip result and row count.
let tipResult = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
Assert.equal(
tipResult.type,
UrlbarUtils.RESULT_TYPE.TIP,
"Result at index 1 is a tip"
);
let tipResultSpan = UrlbarUtils.getSpanForResult(
tipResult.element.row.result
);
Assert.greater(tipResultSpan, 1, "Sanity check: Tip has large result span");
let expectedRowCount = maxResults - tipResultSpan + 1;
Assert.equal(
UrlbarTestUtils.getResultCount(window),
expectedRowCount,
"Sanity check: Initial row count takes tip result span into account"
);
// Second search: Change the provider's results so that it has enough history
// to fill up the view. Search suggestion rows cannot be updated to history
// results, so the view will append the history results as new rows.
provider._results = queryStrings.map(title => {
let url = "http://example.com/" + title;
return new UrlbarResult(
UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
{
title,
url,
displayUrl: "http://example.com/" + title,
}
);
});
// Don't allow the search to finish until we check the updated rows. We'll
// accomplish that by adding a mutation observer on the rows and delaying
// resolving the provider's finishQueryPromise. When all new rows have been
// added, we expect the new row count to be:
//
// expectedRowCount // the original row count
// + (expectedRowCount - 2) // the newly added history row count (hidden)
// --------------------------
// (2 * expectedRowCount) - 2
//
// The `- 2` subtracts the heuristic and tip result.
let newExpectedRowCount = 2 * expectedRowCount - 2;
let mutationPromise = new Promise(resolve => {
let observer = new MutationObserver(mutations => {
let childCount = UrlbarTestUtils.getResultCount(window);
info(`Rows mutation observer called, childCount now ${childCount}`);
if (newExpectedRowCount <= childCount) {
observer.disconnect();
resolve();
}
});
observer.observe(UrlbarTestUtils.getResultsContainer(window), {
childList: true,
});
});
// Now do the second search but don't wait for it to finish.
let resolveQuery;
provider.finishQueryPromise = new Promise(
resolve => (resolveQuery = resolve)
);
let queryPromise = UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: queries[1],
});
// Wait for the history rows to be added.
await mutationPromise;
// Check the rows. We can't use UrlbarTestUtils.getDetailsOfResultAt() here
// because it waits for the query to finish.
Assert.equal(
UrlbarTestUtils.getResultCount(window),
newExpectedRowCount,
"New expected row count"
);
// stale search rows
let rows = UrlbarTestUtils.getResultsContainer(window).children;
for (let i = 2; i < expectedRowCount; i++) {
let row = rows[i];
Assert.equal(
row.result.type,
UrlbarUtils.RESULT_TYPE.SEARCH,
`Result at index ${i} is a search result`
);
Assert.ok(
BrowserTestUtils.is_visible(row),
`Search result at index ${i} is visible`
);
Assert.equal(
row.getAttribute("stale"),
"true",
`Search result at index ${i} is stale`
);
}
// new hidden history rows
for (let i = expectedRowCount; i < newExpectedRowCount; i++) {
let row = rows[i];
Assert.equal(
row.result.type,
UrlbarUtils.RESULT_TYPE.URL,
`Result at index ${i} is a URL result`
);
Assert.ok(
!BrowserTestUtils.is_visible(row),
`URL result at index ${i} is hidden`
);
Assert.ok(
!row.hasAttribute("stale"),
`URL result at index ${i} is not stale`
);
}
// Finish the query, and we're done.
resolveQuery();
await queryPromise;
await UrlbarTestUtils.promisePopupClose(window);
gURLBar.handleRevert();
// We unregister the provider above in a cleanup function so we don't
// accidentally interfere with later tests, but do it here too in case we add
// more tasks to this test. It's harmless to call more than once.
UrlbarProvidersManager.unregisterProvider(provider);
});
|