gecko-dev/browser/components/urlbar/tests/browser-updateResults/browser_reuse.js
Drew Willcoxon 3dd0ab83c1 Bug 1701193 - Don't place suggestedIndex results in the wrong spot during view updates. r=mak
This should fix flickering related to suggested indexes once and for all, knock
on wood. It fixes the view-update logic so that if we encounter a new
suggestedIndex result that can't be placed in the correct spot during the first
loop, we stop trying to update rows at that point and instead mark the remaining
rows as stale. Then we reach the loop that appends the remaining results, and we
append them all starting with the suggestedIndex result. Those results are
hidden at first so that the suggestedIndex result never appears in the wrong
spot.

This fixes bug 1701193 and the flickering problem I noted in bug 1701136. It
also fixes the flicker we have right now with the tab-to-search onboarding
result, where during the view update we briefly have 10 results in the view even
though there should only be 9 since the tab-to-search has a span of 2.

At first I had one big test file for this, but not surprisingly it timed out on
some try machines. So I split it up, moved the new files to a new directory, and
moved the two existing browser_updateRows tests there too.

The new tests all do two searches where the first search returns search
suggestions and the second returns URL results. It would be good to test the
opposite too but this patch is already big enough.

Differential Revision: https://phabricator.services.mozilla.com/D110365
2021-04-01 19:26:43 +00:00

235 lines
6.5 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests row updating and reuse.
"use strict";
let TEST_BASE_URL = "http://example.com/";
// A URL result is replaced with a tip result and then vice versa.
add_task(async function urlToTip() {
// Add some visits that will be matched by a "test" search string.
await PlacesTestUtils.addVisits([
"http://example.com/testxx",
"http://example.com/test",
]);
// Add a provider that returns a tip result when the search string is "testx".
let tipResult = new UrlbarResult(
UrlbarUtils.RESULT_TYPE.TIP,
UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
{
text: "This is a test tip.",
buttonText: "OK",
helpUrl: "http://example.com/",
type: "test",
}
);
tipResult.suggestedIndex = 1;
let provider = new UrlbarTestUtils.TestProvider({
results: [tipResult],
});
provider.isActive = context => context.searchString == "testx";
UrlbarProvidersManager.registerProvider(provider);
// Search for "test".
await UrlbarTestUtils.promiseAutocompleteResultPopup({
value: "test",
window,
});
// The result at index 1 should be the http://example.com/test visit.
await checkResult(
1,
UrlbarUtils.RESULT_TYPE.URL,
{
title: "test visit for http://example.com/test",
tagsContainer: null,
titleSeparator: null,
action: "",
url: TEST_BASE_URL + "test",
},
["tipButton", "helpButton"]
);
// Type an "x" so that the search string is "testx".
EventUtils.synthesizeKey("x");
await UrlbarTestUtils.promiseSearchComplete(window);
// Now the result at index 1 should be the tip from our provider.
await checkResult(
1,
UrlbarUtils.RESULT_TYPE.TIP,
{
title: "This is a test tip.",
tipButton: "OK",
helpButton: null,
},
["tagsContainer", "titleSeparator", "action", "url"]
);
// Type another "x" so that the search string is "testxx".
EventUtils.synthesizeKey("x");
await UrlbarTestUtils.promiseSearchComplete(window);
// The result at index 1 should be the http://example.com/testxx visit.
await checkResult(
1,
UrlbarUtils.RESULT_TYPE.URL,
{
title: "test visit for http://example.com/testxx",
tagsContainer: null,
titleSeparator: null,
action: "",
url: TEST_BASE_URL + "testxx",
},
["tipButton", "helpButton"]
);
// Backspace so that the search string is "testx" again.
EventUtils.synthesizeKey("KEY_Backspace");
await UrlbarTestUtils.promiseSearchComplete(window);
// The result at index 1 should be the tip again.
await checkResult(
1,
UrlbarUtils.RESULT_TYPE.TIP,
{
title: "This is a test tip.",
tipButton: "OK",
helpButton: null,
},
["tagsContainer", "titleSeparator", "action", "url"]
);
await UrlbarTestUtils.promisePopupClose(window, () => {
EventUtils.synthesizeKey("KEY_Escape");
});
UrlbarProvidersManager.unregisterProvider(provider);
await PlacesUtils.history.clear();
});
// A tip result is replaced with URL result and then vice versa.
add_task(async function tipToURL() {
// Add a visit that will be matched by a "testx" search string.
await PlacesTestUtils.addVisits("http://example.com/testx");
// Add a provider that returns a tip result when the search string is "test"
// or "testxx".
let tipResult = new UrlbarResult(
UrlbarUtils.RESULT_TYPE.TIP,
UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
{
text: "This is a test tip.",
buttonText: "OK",
helpUrl: "http://example.com/",
type: "test",
}
);
tipResult.suggestedIndex = 1;
let provider = new UrlbarTestUtils.TestProvider({
results: [tipResult],
});
provider.isActive = context =>
["test", "testxx"].includes(context.searchString);
UrlbarProvidersManager.registerProvider(provider);
// Search for "test".
await UrlbarTestUtils.promiseAutocompleteResultPopup({
value: "test",
window,
});
// The result at index 1 should be the tip from our provider.
await checkResult(
1,
UrlbarUtils.RESULT_TYPE.TIP,
{
title: "This is a test tip.",
tipButton: "OK",
helpButton: null,
},
["tagsContainer", "titleSeparator", "action", "url"]
);
// Type an "x" so that the search string is "testx".
EventUtils.synthesizeKey("x");
await UrlbarTestUtils.promiseSearchComplete(window);
// Now the result at index 1 should be the visit.
await checkResult(
1,
UrlbarUtils.RESULT_TYPE.URL,
{
title: "test visit for http://example.com/testx",
tagsContainer: null,
titleSeparator: null,
action: "",
url: TEST_BASE_URL + "testx",
},
["tipButton", "helpButton"]
);
// Type another "x" so that the search string is "testxx".
EventUtils.synthesizeKey("x");
await UrlbarTestUtils.promiseSearchComplete(window);
// The result at index 1 should be the tip again.
await checkResult(
1,
UrlbarUtils.RESULT_TYPE.TIP,
{
title: "This is a test tip.",
tipButton: "OK",
helpButton: null,
},
["tagsContainer", "titleSeparator", "action", "url"]
);
// Backspace so that the search string is "testx" again.
EventUtils.synthesizeKey("KEY_Backspace");
await UrlbarTestUtils.promiseSearchComplete(window);
// The result at index 1 should be the visit again.
await checkResult(
1,
UrlbarUtils.RESULT_TYPE.URL,
{
title: "test visit for http://example.com/testx",
tagsContainer: null,
titleSeparator: null,
action: "",
url: TEST_BASE_URL + "testx",
},
["tipButton", "helpButton"]
);
await UrlbarTestUtils.promisePopupClose(window, () => {
EventUtils.synthesizeKey("KEY_Escape");
});
UrlbarProvidersManager.unregisterProvider(provider);
await PlacesUtils.history.clear();
});
async function checkResult(index, type, presentElements, absentElements) {
let result = await UrlbarTestUtils.getDetailsOfResultAt(window, index);
Assert.equal(result.type, type, "Expected result type");
for (let [name, value] of Object.entries(presentElements)) {
let element = result.element.row._elements.get(name);
Assert.ok(element, `${name} should be present`);
if (typeof value == "string") {
Assert.equal(
element.textContent,
value,
`${name} value should be correct`
);
}
}
for (let name of absentElements) {
let element = result.element.row._elements.get(name);
Assert.ok(!element, `${name} should be absent`);
}
}