author | Mark Banner <standard8@mozilla.com> |
Thu, 28 Feb 2019 09:25:36 +0000 | |
changeset 461709 | bacf3a98194bc506c75c437ed23e64e97b2c5e0f |
parent 461708 | ff76466ee236c1d23bed762eb5de658db038147e |
child 461710 | 694837e25cc6bb0b68fc3e8771bef3f92249346b |
push id | 35627 |
push user | opoprus@mozilla.com |
push date | Thu, 28 Feb 2019 21:44:07 +0000 |
treeherder | mozilla-central@db533ea3d561 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mak |
bugs | 1522508 |
milestone | 67.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/components/extensions/test/browser/browser_ext_omnibox.js +++ b/browser/components/extensions/test/browser/browser_ext_omnibox.js @@ -1,12 +1,14 @@ /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* vim: set sts=2 sw=2 et tw=80: */ "use strict"; +const {UrlbarTestUtils} = ChromeUtils.import("resource://testing-common/UrlbarTestUtils.jsm"); + add_task(async function() { // This keyword needs to be unique to prevent history entries from unrelated // tests from appearing in the suggestions list. let keyword = "VeryUniqueKeywordThatDoesNeverMatchAnyTestUrl"; let extension = ExtensionTestUtils.loadExtension({ manifest: { "omnibox": { @@ -76,47 +78,44 @@ add_task(async function() { `Expected "${event}" to have fired with text: "${expected.text}".`); } if (expected.disposition) { is(actual.disposition, expected.disposition, `Expected "${event}" to have fired with disposition: "${expected.disposition}".`); } } - async function waitForAutocompleteResultAt(index) { - let searchString = gURLBar.controller.searchString; - await BrowserTestUtils.waitForCondition( - () => gURLBar.popup.richlistbox.itemChildren.length > index && - gURLBar.popup.richlistbox.itemChildren[index].getAttribute("ac-text") == searchString, - `Waiting for the autocomplete result for "${searchString}" at [${index}] to appear`); + async function waitForResult(index, searchString) { + let result = await UrlbarTestUtils.getDetailsOfResultAt(window, index); // Ensure the addition is complete, for proper mouse events on the entries. await new Promise(resolve => window.requestIdleCallback(resolve, {timeout: 1000})); - return gURLBar.popup.richlistbox.itemChildren[index]; + return result; } - async function promiseClickOnItem(item, details) { + async function promiseClickOnItem(index, details) { // The Address Bar panel is animated and updated on a timer, thus it may not // yet be listening to events when we try to click on it. This uses a // polling strategy to repeat the click, if it doesn't go through. let clicked = false; - item.addEventListener("mousedown", () => { clicked = true; }, {once: true}); + let element = await UrlbarTestUtils.waitForAutocompleteResultAt(window, index); + element.addEventListener("mousedown", () => { clicked = true; }, {once: true}); while (!clicked) { - EventUtils.synthesizeMouseAtCenter(item, details); + EventUtils.synthesizeMouseAtCenter(element, details); await new Promise(r => window.requestIdleCallback(r, {timeout: 1000})); } } let inputSessionSerial = 0; async function startInputSession() { gURLBar.focus(); gURLBar.value = keyword; EventUtils.sendString(" "); await expectEvent("on-input-started-fired"); // Always use a different input at every invokation, so that - // waitForAutocompleteResultAt can distinguish different cases. + // waitForResult can distinguish different cases. let char = ((inputSessionSerial++) % 10).toString(); EventUtils.sendString(char); await expectEvent("on-input-changed-fired", {text: char}); return char; } async function testInputEvents() { @@ -182,88 +181,85 @@ add_task(async function() { suggestion: { description: expectedText, }, }); await extension.awaitMessage("default-suggestion-set"); } let text = await startInputSession(); - await waitForAutocompleteResultAt(0); - - let item = gURLBar.popup.richlistbox.itemChildren[0]; + let result = await waitForResult(0); - is(item.getAttribute("title"), expectedText, - `Expected heuristic result to have title: "${expectedText}".`); + Assert.equal(result.displayed.title, expectedText, + `Expected heuristic result to have title: "${expectedText}".`); - is(item.getAttribute("displayurl"), `${keyword} ${text}`, - `Expected heuristic result to have displayurl: "${keyword} ${text}".`); + Assert.equal(result.displayed.action, `${keyword} ${text}`, + `Expected heuristic result to have displayurl: "${keyword} ${text}".`); let promiseEvent = expectEvent("on-input-entered-fired", { text, disposition: "currentTab", }); - await promiseClickOnItem(item, {}); + await promiseClickOnItem(0, {}); await promiseEvent; } async function testDisposition(suggestionIndex, expectedDisposition, expectedText) { await startInputSession(); - await waitForAutocompleteResultAt(suggestionIndex); + await waitForResult(suggestionIndex); // Select the suggestion. EventUtils.synthesizeKey("KEY_ArrowDown", {repeat: suggestionIndex}); let promiseEvent = expectEvent("on-input-entered-fired", { text: expectedText, disposition: expectedDisposition, }); - let item = gURLBar.popup.richlistbox.itemChildren[suggestionIndex]; if (expectedDisposition == "currentTab") { - await promiseClickOnItem(item, {}); + await promiseClickOnItem(suggestionIndex, {}); } else if (expectedDisposition == "newForegroundTab") { - await promiseClickOnItem(item, {accelKey: true}); + await promiseClickOnItem(suggestionIndex, {accelKey: true}); } else if (expectedDisposition == "newBackgroundTab") { - await promiseClickOnItem(item, {shiftKey: true, accelKey: true}); + await promiseClickOnItem(suggestionIndex, {shiftKey: true, accelKey: true}); } await promiseEvent; } async function testSuggestions(info) { extension.sendMessage("set-synchronous", {synchronous: false}); await extension.awaitMessage("set-synchronous-set"); - function expectSuggestion({content, description}, index) { - let item = gURLBar.popup.richlistbox.itemChildren[index + 1]; // Skip the heuristic result. - - ok(!!item, "Expected item to exist"); - is(item.getAttribute("title"), description, - `Expected suggestion to have title: "${description}".`); - - is(item.getAttribute("displayurl"), `${keyword} ${content}`, - `Expected suggestion to have displayurl: "${keyword} ${content}".`); + let text = await startInputSession(); + if (!UrlbarPrefs.get("quantumbar")) { + // TODO Bug 1530338: We can't yet wait for a specific result for the + // quantumbar. Therefore we just skip this for now. + await waitForResult(0); } - let text = await startInputSession(); - // Even if the results are generated asynchronously, - // the heuristic result should always be present. - await waitForAutocompleteResultAt(0); - extension.sendMessage(info.test); await extension.awaitMessage("test-ready"); - await waitForAutocompleteResultAt(info.suggestions.length - 1); - info.suggestions.forEach(expectSuggestion); + await waitForResult(info.suggestions.length - 1); + // Skip the heuristic result. + let index = 1; + for (let {content, description} of info.suggestions) { + let item = await UrlbarTestUtils.getDetailsOfResultAt(window, index); + Assert.equal(item.displayed.title, description, + `Expected suggestion to have title: "${description}".`); + Assert.equal(item.displayed.action, `${keyword} ${content}`, + `Expected suggestion to have displayurl: "${keyword} ${content}".`); + index++; + } let promiseEvent = expectEvent("on-input-entered-fired", { text, disposition: "currentTab", }); - await promiseClickOnItem(gURLBar.popup.richlistbox.itemChildren[0], {}); + await promiseClickOnItem(0, {}); await promiseEvent; } await extension.startup(); await SimpleTest.promiseFocus(window); await testInputEvents();
--- a/browser/components/urlbar/tests/UrlbarTestUtils.jsm +++ b/browser/components/urlbar/tests/UrlbarTestUtils.jsm @@ -294,17 +294,17 @@ class UrlbarAbstraction { promiseSearchComplete() { if (this.quantumbar) { return this.urlbar.lastQueryContextPromise; } return BrowserTestUtils.waitForCondition( () => this.urlbar.controller.searchStatus >= Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH, - "waiting urlbar search to complete"); + "waiting urlbar search to complete", 100, 50); } async promiseResultAt(index) { if (!this.quantumbar) { // In the legacy address bar, old results are replaced when new results // arrive, thus it's possible for a result to be present but refer to // a previous query. This ensures the given result refers to the current // query by checking its query string against the string being searched
--- a/toolkit/components/places/UnifiedComplete.jsm +++ b/toolkit/components/places/UnifiedComplete.jsm @@ -1707,17 +1707,20 @@ Search.prototype = { // matches may appear stale for a long time. // This is necessary because WebExtensions don't have a method to notify // that they are done providing results, so they could be pending forever. setTimeout(() => this._cleanUpNonCurrentMatches(UrlbarUtils.RESULT_GROUP.EXTENSION), 100); // Since the extension has no way to signale when it's done pushing // results, we add a timeout racing with the addition. let timeoutPromise = new Promise(resolve => { - setTimeout(resolve, MAXIMUM_ALLOWED_EXTENSION_TIME_MS); + let timer = setTimeout(resolve, MAXIMUM_ALLOWED_EXTENSION_TIME_MS); + // TODO Bug 1531268: Figure out why this cancel helps makes the tests + // stable. + promise.then(timer.cancel); }); return Promise.race([timeoutPromise, promise]).catch(Cu.reportError); }, async _matchRemoteTabs() { // Bail out early for non-sync users. if (!syncUsernamePref) { return;