summaryrefslogtreecommitdiffstats
path: root/browser/components/urlbar/tests/quicksuggest
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/urlbar/tests/quicksuggest')
-rw-r--r--browser/components/urlbar/tests/quicksuggest/MerinoTestUtils.sys.mjs18
-rw-r--r--browser/components/urlbar/tests/quicksuggest/RemoteSettingsServer.sys.mjs30
-rw-r--r--browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js3
-rw-r--r--browser/components/urlbar/tests/quicksuggest/browser/browser_telemetry_impressionEdgeCases.js2
-rw-r--r--browser/components/urlbar/tests/quicksuggest/browser/browser_weather.js107
-rw-r--r--browser/components/urlbar/tests/quicksuggest/browser/head.js82
-rw-r--r--browser/components/urlbar/tests/quicksuggest/unit/head.js113
-rw-r--r--browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest.js58
-rw-r--r--browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js12
-rw-r--r--browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_pocket.js4
-rw-r--r--browser/components/urlbar/tests/quicksuggest/unit/test_rust_ingest.js33
-rw-r--r--browser/components/urlbar/tests/quicksuggest/unit/test_weather.js200
-rw-r--r--browser/components/urlbar/tests/quicksuggest/unit/test_weather_keywords.js139
-rw-r--r--browser/components/urlbar/tests/quicksuggest/unit/xpcshell.toml1
14 files changed, 473 insertions, 329 deletions
diff --git a/browser/components/urlbar/tests/quicksuggest/MerinoTestUtils.sys.mjs b/browser/components/urlbar/tests/quicksuggest/MerinoTestUtils.sys.mjs
index 6cda9bb9a7..1828ddbceb 100644
--- a/browser/components/urlbar/tests/quicksuggest/MerinoTestUtils.sys.mjs
+++ b/browser/components/urlbar/tests/quicksuggest/MerinoTestUtils.sys.mjs
@@ -355,20 +355,16 @@ class _MerinoTestUtils {
lazy.QuickSuggest.weather._test_fetchIntervalMs = WEATHER_FETCH_INTERVAL_MS;
- // Enabling weather will trigger a fetch. Wait for it to finish so the
- // suggestion is ready when this function returns.
- this.info("MockMerinoServer initializing weather, waiting for fetch");
- let fetchPromise = lazy.QuickSuggest.weather.waitForFetches();
+ // Enabling weather will trigger a fetch. Queue another fetch and await it
+ // so no fetches are ongoing when this function returns.
+ this.info("MockMerinoServer initializing weather, setting prefs");
lazy.UrlbarPrefs.set("weather.featureGate", true);
lazy.UrlbarPrefs.set("suggest.weather", true);
- await fetchPromise;
- this.info("MockMerinoServer initializing weather, got fetch");
-
- this.Assert.equal(
- lazy.QuickSuggest.weather._test_pendingFetchCount,
- 0,
- "No pending fetches after awaiting initial fetch"
+ this.info(
+ "MockMerinoServer initializing weather, done setting prefs, starting fetch"
);
+ await lazy.QuickSuggest.weather._test_fetch();
+ this.info("MockMerinoServer initializing weather, done awaiting fetch");
this.registerCleanupFunction?.(async () => {
lazy.UrlbarPrefs.clear("weather.featureGate");
diff --git a/browser/components/urlbar/tests/quicksuggest/RemoteSettingsServer.sys.mjs b/browser/components/urlbar/tests/quicksuggest/RemoteSettingsServer.sys.mjs
index 32b42198c3..c2aeca1991 100644
--- a/browser/components/urlbar/tests/quicksuggest/RemoteSettingsServer.sys.mjs
+++ b/browser/components/urlbar/tests/quicksuggest/RemoteSettingsServer.sys.mjs
@@ -9,7 +9,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
HttpError: "resource://testing-common/httpd.sys.mjs",
HttpServer: "resource://testing-common/httpd.sys.mjs",
HTTP_404: "resource://testing-common/httpd.sys.mjs",
- Log: "resource://gre/modules/Log.sys.mjs",
});
const SERVER_PREF = "services.settings.server";
@@ -23,23 +22,16 @@ export class RemoteSettingsServer {
* The server must be started by calling `start()`.
*
* @param {object} options
- * @param {number} options.logLevel
- * A `Log.Level` value from `Log.sys.mjs`. `Log.Level.Info` logs basic info
- * on requests and responses like paths and status codes. Pass
- * `Log.Level.Debug` to log more info like headers, response bodies, and
- * added and removed records.
+ * @param {number} options.maxLogLevel
+ * A log level value as defined by ConsoleInstance. `Info` logs basic info
+ * on requests and responses like paths and status codes. Pass `Debug` to
+ * log more info like headers, response bodies, added and removed records.
*/
- constructor({ logLevel = lazy.Log.Level.Info } = {}) {
- this.#log = lazy.Log.repository.getLogger("RemoteSettingsServer");
- this.#log.level = logLevel;
-
- // Use `DumpAppender` instead of `ConsoleAppender`. The xpcshell and browser
- // test harnesses buffer console messages and log them later, which makes it
- // really hard to debug problems. `DumpAppender` logs to stdout, which the
- // harnesses log immediately.
- this.#log.addAppender(
- new lazy.Log.DumpAppender(new lazy.Log.BasicFormatter())
- );
+ constructor({ maxLogLevel = "Info" } = {}) {
+ this.#log = console.createInstance({
+ prefix: "RemoteSettingsServer",
+ maxLogLevel,
+ });
}
/**
@@ -587,14 +579,12 @@ export class RemoteSettingsServer {
* The associated request.
* @param {integer} options.status
* The HTTP status code of the response.
- * @param {string} options.statusText
- * The description of the status code.
* @param {object} options.headers
* An object mapping from response header names to values.
* @param {object} options.body
* The response body, if any.
*/
- #logResponse({ request, status, statusText, headers, body }) {
+ #logResponse({ request, status, headers, body }) {
this.#log.info(`> ${status} ${request.path}`);
for (let [name, value] of Object.entries(headers)) {
this.#log.debug(`${name}: ${value}`);
diff --git a/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js b/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js
index 6256a5aec2..dbd8f59ade 100644
--- a/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js
+++ b/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js
@@ -373,7 +373,6 @@ const VARIATION_TEST_DATA = [
"onboardingNext",
"onboardingAccept",
"onboardingLearnMore",
- "onboardingReject",
"onboardingSkipLink",
"onboardingDialog",
"onboardingAccept",
@@ -706,7 +705,6 @@ const VARIATION_TEST_DATA = [
"onboardingNext",
"onboardingLearnMore",
"onboardingAccept",
- "onboardingReject",
"onboardingSkipLink",
"onboardingDialog",
"onboardingLearnMore",
@@ -762,7 +760,6 @@ const VARIATION_TEST_DATA = [
defaultFocusOrder: [
"onboardingLearnMore",
"onboardingAccept",
- "onboardingReject",
"onboardingSkipLink",
"onboardingDialog",
"onboardingLearnMore",
diff --git a/browser/components/urlbar/tests/quicksuggest/browser/browser_telemetry_impressionEdgeCases.js b/browser/components/urlbar/tests/quicksuggest/browser/browser_telemetry_impressionEdgeCases.js
index 8682f1f53a..821c5cf470 100644
--- a/browser/components/urlbar/tests/quicksuggest/browser/browser_telemetry_impressionEdgeCases.js
+++ b/browser/components/urlbar/tests/quicksuggest/browser/browser_telemetry_impressionEdgeCases.js
@@ -172,7 +172,7 @@ add_task(async function hiddenRow() {
// mutation listener to the view so we can tell when the quick suggest row is
// added.
let mutationPromise = new Promise(resolve => {
- let observer = new MutationObserver(mutations => {
+ let observer = new MutationObserver(() => {
let rows = UrlbarTestUtils.getResultsContainer(window).children;
for (let row of rows) {
if (row.result.providerName == "UrlbarProviderQuickSuggest") {
diff --git a/browser/components/urlbar/tests/quicksuggest/browser/browser_weather.js b/browser/components/urlbar/tests/quicksuggest/browser/browser_weather.js
index 1c3f0e62e7..e10e87b516 100644
--- a/browser/components/urlbar/tests/quicksuggest/browser/browser_weather.js
+++ b/browser/components/urlbar/tests/quicksuggest/browser/browser_weather.js
@@ -11,6 +11,11 @@ ChromeUtils.defineESModuleGetters(this, {
UrlbarProviderWeather: "resource:///modules/UrlbarProviderWeather.sys.mjs",
});
+// This test takes a while and can time out in verify mode. Each task is run
+// twice, once with Rust enabled and once with it disabled. Once we remove the
+// JS backend this should improve a lot, but for now request a longer timeout.
+requestLongerTimeout(5);
+
add_setup(async function () {
await QuickSuggestTestUtils.ensureQuickSuggestInit({
remoteSettingsRecords: [
@@ -21,6 +26,15 @@ add_setup(async function () {
],
});
await MerinoTestUtils.initWeather();
+
+ // When `add_tasks_with_rust()` disables the Rust backend and forces sync, the
+ // JS backend will sync `Weather` with remote settings. Since keywords are
+ // present in remote settings at that point (we added them above), `Weather`
+ // will then start fetching. The fetch may or may not be done before our test
+ // task starts. To make sure it's done, queue another fetch and await it.
+ registerAddTasksWithRustSetup(async () => {
+ await QuickSuggest.weather._test_fetch();
+ });
});
// Basic checks of the row DOM.
@@ -341,11 +355,8 @@ async function doDismissTest(command) {
await UrlbarTestUtils.promisePopupClose(window);
// Enable the weather suggestion again and wait for it to be fetched.
- let fetchPromise = QuickSuggest.weather.waitForFetches();
UrlbarPrefs.clear("suggest.weather");
- info("Waiting for weather fetch after re-enabling the suggestion");
- await fetchPromise;
- info("Got weather fetch");
+ await QuickSuggest.weather._test_fetch();
// Wait for keywords to be re-synced from remote settings.
await QuickSuggestTestUtils.forceSync();
@@ -396,6 +407,94 @@ async function doSessionOngoingCommandTest(command) {
await doDismissTest("not_interested");
}
+// Test for menu item to mange the suggest.
+add_tasks_with_rust(async function manage() {
+ await BrowserTestUtils.withNewTab({ gBrowser }, async browser => {
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: MerinoTestUtils.WEATHER_KEYWORD,
+ });
+
+ let resultIndex = 1;
+ let details = await UrlbarTestUtils.getDetailsOfResultAt(
+ window,
+ resultIndex
+ );
+ assertIsWeatherResult(details.result, true);
+
+ const managePage = "about:preferences#search";
+ let onManagePageLoaded = BrowserTestUtils.browserLoaded(
+ browser,
+ false,
+ managePage
+ );
+ // Click the command.
+ await UrlbarTestUtils.openResultMenuAndClickItem(window, "manage", {
+ resultIndex,
+ });
+ await onManagePageLoaded;
+ Assert.equal(
+ browser.currentURI.spec,
+ managePage,
+ "The manage page is loaded"
+ );
+
+ await UrlbarTestUtils.promisePopupClose(window);
+ });
+});
+
+// Test for simple UI.
+add_tasks_with_rust(async function simpleUI() {
+ const testData = [
+ {
+ weatherSimpleUI: true,
+ expectedSummary:
+ MerinoTestUtils.WEATHER_SUGGESTION.current_conditions.summary,
+ },
+ {
+ weatherSimpleUI: false,
+ expectedSummary: `${MerinoTestUtils.WEATHER_SUGGESTION.current_conditions.summary}; ${MerinoTestUtils.WEATHER_SUGGESTION.forecast.summary}`,
+ },
+ ];
+
+ for (let { weatherSimpleUI, expectedSummary } of testData) {
+ let nimbusCleanup = await UrlbarTestUtils.initNimbusFeature({
+ weatherSimpleUI,
+ });
+
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: MerinoTestUtils.WEATHER_KEYWORD,
+ });
+
+ let resultIndex = 1;
+ let details = await UrlbarTestUtils.getDetailsOfResultAt(
+ window,
+ resultIndex
+ );
+ assertIsWeatherResult(details.result, true);
+
+ let { row } = details.element;
+ let summary = row.querySelector(".urlbarView-dynamic-weather-summaryText");
+
+ // `getViewUpdate()` is allowed to be async and `UrlbarView` awaits it even
+ // though the `Weather` implementation is not async. That means the summary
+ // text content will be updated asyncly, so we need to wait for it.
+ await TestUtils.waitForCondition(
+ () => summary.textContent == expectedSummary,
+ "Waiting for the row's summary text to be updated"
+ );
+ Assert.equal(
+ summary.textContent,
+ expectedSummary,
+ "The summary text should be correct"
+ );
+
+ await UrlbarTestUtils.promisePopupClose(window);
+ await nimbusCleanup();
+ }
+});
+
function assertIsWeatherResult(result, isWeatherResult) {
let provider = UrlbarPrefs.get("quickSuggestRustEnabled")
? UrlbarProviderQuickSuggest
diff --git a/browser/components/urlbar/tests/quicksuggest/browser/head.js b/browser/components/urlbar/tests/quicksuggest/browser/head.js
index 7d62a44d45..cc5f449e94 100644
--- a/browser/components/urlbar/tests/quicksuggest/browser/head.js
+++ b/browser/components/urlbar/tests/quicksuggest/browser/head.js
@@ -636,20 +636,49 @@ function _assertGleanPing(ping) {
}
}
+let gAddTasksWithRustSetup;
+
/**
* Adds two tasks: One with the Rust backend disabled and one with it enabled.
* The names of the task functions will be the name of the passed-in task
- * function appended with "_rustDisabled" and "_rustEnabled" respectively. Call
- * with the usual `add_task()` arguments.
+ * function appended with "_rustDisabled" and "_rustEnabled". If the passed-in
+ * task doesn't have a name, "anonymousTask" will be used.
+ *
+ * Call this with the usual `add_task()` arguments. Additionally, an object with
+ * the following properties can be specified as any argument:
+ *
+ * {boolean} skip_if_rust_enabled
+ * If true, a "_rustEnabled" task won't be added. Useful when Rust is enabled
+ * by default but the task doesn't make sense with Rust and you still want to
+ * test some behavior when Rust is disabled.
*
* @param {...any} args
* The usual `add_task()` arguments.
*/
function add_tasks_with_rust(...args) {
+ let skipIfRustEnabled = false;
+ let i = args.findIndex(a => a.skip_if_rust_enabled);
+ if (i >= 0) {
+ skipIfRustEnabled = true;
+ args.splice(i, 1);
+ }
+
let taskFnIndex = args.findIndex(a => typeof a == "function");
let taskFn = args[taskFnIndex];
for (let rustEnabled of [false, true]) {
+ let newTaskName =
+ (taskFn.name || "anonymousTask") +
+ (rustEnabled ? "_rustEnabled" : "_rustDisabled");
+
+ if (rustEnabled && skipIfRustEnabled) {
+ info(
+ "add_tasks_with_rust: Skipping due to skip_if_rust_enabled: " +
+ newTaskName
+ );
+ continue;
+ }
+
let newTaskFn = async (...taskFnArgs) => {
info("add_tasks_with_rust: Setting rustEnabled: " + rustEnabled);
UrlbarPrefs.set("quicksuggest.rustEnabled", rustEnabled);
@@ -660,12 +689,30 @@ function add_tasks_with_rust(...args) {
await QuickSuggestTestUtils.forceSync();
info("add_tasks_with_rust: Done forcing sync");
+ if (gAddTasksWithRustSetup) {
+ info("add_tasks_with_rust: Calling setup function");
+ await gAddTasksWithRustSetup();
+ info("add_tasks_with_rust: Done calling setup function");
+ }
+
let rv;
try {
info(
"add_tasks_with_rust: Calling original task function: " + taskFn.name
);
rv = await taskFn(...taskFnArgs);
+ } catch (e) {
+ // Clearly report any unusual errors to make them easier to spot and to
+ // make the flow of the test clearer. The harness throws NS_ERROR_ABORT
+ // when a normal assertion fails, so don't report that.
+ if (e.result != Cr.NS_ERROR_ABORT) {
+ Assert.ok(
+ false,
+ "add_tasks_with_rust: The original task function threw an error: " +
+ e
+ );
+ }
+ throw e;
} finally {
info(
"add_tasks_with_rust: Done calling original task function: " +
@@ -683,11 +730,32 @@ function add_tasks_with_rust(...args) {
return rv;
};
- Object.defineProperty(newTaskFn, "name", {
- value: taskFn.name + (rustEnabled ? "_rustEnabled" : "_rustDisabled"),
- });
- let addTaskArgs = [...args];
- addTaskArgs[taskFnIndex] = newTaskFn;
+ Object.defineProperty(newTaskFn, "name", { value: newTaskName });
+
+ let addTaskArgs = [];
+ for (let j = 0; j < args.length; j++) {
+ addTaskArgs[j] =
+ j == taskFnIndex
+ ? newTaskFn
+ : Cu.cloneInto(args[j], this, { cloneFunctions: true });
+ }
add_task(...addTaskArgs);
}
}
+
+/**
+ * Registers a setup function that `add_tasks_with_rust()` will await before
+ * calling each of your original tasks. Call this at most once in your test file
+ * (i.e., in `add_setup()`). This is useful when enabling/disabling Rust has
+ * side effects related to your particular test that need to be handled or
+ * awaited for each of your tasks. On the other hand, if only one or two of your
+ * tasks need special setup, do it directly in those tasks instead of using
+ * this. The passed-in `setupFn` is automatically unregistered on cleanup.
+ *
+ * @param {Function} setupFn
+ * A function that will be awaited before your original tasks are called.
+ */
+function registerAddTasksWithRustSetup(setupFn) {
+ gAddTasksWithRustSetup = setupFn;
+ registerCleanupFunction(() => (gAddTasksWithRustSetup = null));
+}
diff --git a/browser/components/urlbar/tests/quicksuggest/unit/head.js b/browser/components/urlbar/tests/quicksuggest/unit/head.js
index c468e4526f..73bedf468e 100644
--- a/browser/components/urlbar/tests/quicksuggest/unit/head.js
+++ b/browser/components/urlbar/tests/quicksuggest/unit/head.js
@@ -20,18 +20,49 @@ add_setup(async function setUpQuickSuggestXpcshellTest() {
UrlbarPrefs._testSkipTelemetryEnvironmentInit = true;
});
+let gAddTasksWithRustSetup;
+
/**
* Adds two tasks: One with the Rust backend disabled and one with it enabled.
* The names of the task functions will be the name of the passed-in task
* function appended with "_rustDisabled" and "_rustEnabled". If the passed-in
- * task doesn't have a name, "anonymousTask" will be used. Call this with the
- * usual `add_task()` arguments.
+ * task doesn't have a name, "anonymousTask" will be used.
+ *
+ * Call this with the usual `add_task()` arguments. Additionally, an object with
+ * the following properties can be specified as any argument:
+ *
+ * {boolean} skip_if_rust_enabled
+ * If true, a "_rustEnabled" task won't be added. Useful when Rust is enabled
+ * by default but the task doesn't make sense with Rust and you still want to
+ * test some behavior when Rust is disabled.
+ *
+ * @param {...any} args
+ * The usual `add_task()` arguments.
*/
function add_tasks_with_rust(...args) {
+ let skipIfRustEnabled = false;
+ let i = args.findIndex(a => a.skip_if_rust_enabled);
+ if (i >= 0) {
+ skipIfRustEnabled = true;
+ args.splice(i, 1);
+ }
+
let taskFnIndex = args.findIndex(a => typeof a == "function");
let taskFn = args[taskFnIndex];
for (let rustEnabled of [false, true]) {
+ let newTaskName =
+ (taskFn.name || "anonymousTask") +
+ (rustEnabled ? "_rustEnabled" : "_rustDisabled");
+
+ if (rustEnabled && skipIfRustEnabled) {
+ info(
+ "add_tasks_with_rust: Skipping due to skip_if_rust_enabled: " +
+ newTaskName
+ );
+ continue;
+ }
+
let newTaskFn = async (...taskFnArgs) => {
info("add_tasks_with_rust: Setting rustEnabled: " + rustEnabled);
UrlbarPrefs.set("quicksuggest.rustEnabled", rustEnabled);
@@ -42,6 +73,12 @@ function add_tasks_with_rust(...args) {
await QuickSuggestTestUtils.forceSync();
info("add_tasks_with_rust: Done forcing sync");
+ if (gAddTasksWithRustSetup) {
+ info("add_tasks_with_rust: Calling setup function");
+ await gAddTasksWithRustSetup();
+ info("add_tasks_with_rust: Done calling setup function");
+ }
+
let rv;
try {
info(
@@ -77,18 +114,36 @@ function add_tasks_with_rust(...args) {
return rv;
};
- Object.defineProperty(newTaskFn, "name", {
- value:
- (taskFn.name || "anonymousTask") +
- (rustEnabled ? "_rustEnabled" : "_rustDisabled"),
- });
- let addTaskArgs = [...args];
- addTaskArgs[taskFnIndex] = newTaskFn;
+ Object.defineProperty(newTaskFn, "name", { value: newTaskName });
+
+ let addTaskArgs = [];
+ for (let j = 0; j < args.length; j++) {
+ addTaskArgs[j] =
+ j == taskFnIndex
+ ? newTaskFn
+ : Cu.cloneInto(args[j], this, { cloneFunctions: true });
+ }
add_task(...addTaskArgs);
}
}
/**
+ * Registers a setup function that `add_tasks_with_rust()` will await before
+ * calling each of your original tasks. Call this at most once in your test file
+ * (i.e., in `add_setup()`). This is useful when enabling/disabling Rust has
+ * side effects related to your particular test that need to be handled or
+ * awaited for each of your tasks. On the other hand, if only one or two of your
+ * tasks need special setup, do it directly in those tasks instead of using
+ * this.
+ *
+ * @param {Function} setupFn
+ * A function that will be awaited before your original tasks are called.
+ */
+function registerAddTasksWithRustSetup(setupFn) {
+ gAddTasksWithRustSetup = setupFn;
+}
+
+/**
* Returns an expected Wikipedia (non-sponsored) result that can be passed to
* `check_results()` regardless of whether the Rust backend is enabled.
*
@@ -106,7 +161,7 @@ function makeWikipediaResult({
iconBlob = new Blob([new Uint8Array([])]),
impressionUrl = "http://example.com/wikipedia-impression",
clickUrl = "http://example.com/wikipedia-click",
- blockId = 1,
+ blockId = 2,
advertiser = "Wikipedia",
iabCategory = "5 - Education",
suggestedIndex = -1,
@@ -362,7 +417,6 @@ function makeWeatherResult({
temperatureUnit,
url: MerinoTestUtils.WEATHER_SUGGESTION.url,
iconId: "6",
- helpUrl: QuickSuggest.HELP_URL,
requestId: MerinoTestUtils.server.response.body.request_id,
source: "merino",
provider: "accuweather",
@@ -909,3 +963,40 @@ async function doRustProvidersTests({ searchString, tests }) {
UrlbarPrefs.clear("quicksuggest.rustEnabled");
await QuickSuggestTestUtils.forceSync();
}
+
+/**
+ * Waits for `Weather` to start and finish a new fetch. Typically you call this
+ * before you know a new fetch will start, save but don't await the promise, do
+ * the thing that triggers the new fetch, and then await the promise to wait for
+ * the fetch to finish.
+ *
+ * If a fetch is currently ongoing, this will first wait for a new fetch to
+ * start, which might not be what you want. If you only want to wait for any
+ * ongoing fetch to finish, await `QuickSuggest.weather.fetchPromise` instead.
+ */
+async function waitForNewWeatherFetch() {
+ let { fetchPromise: oldFetchPromise } = QuickSuggest.weather;
+
+ // Wait for a new fetch to start.
+ let newFetchPromise;
+ await TestUtils.waitForCondition(() => {
+ let { fetchPromise } = QuickSuggest.weather;
+ if (
+ (oldFetchPromise && fetchPromise != oldFetchPromise) ||
+ (!oldFetchPromise && fetchPromise)
+ ) {
+ newFetchPromise = fetchPromise;
+ return true;
+ }
+ return false;
+ }, "Waiting for a new weather fetch to start");
+
+ Assert.equal(
+ QuickSuggest.weather.fetchPromise,
+ newFetchPromise,
+ "Sanity check: fetchPromise hasn't changed since waitForCondition returned"
+ );
+
+ // Wait for the new fetch to finish.
+ await newFetchPromise;
+}
diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest.js b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest.js
index e4c145aabb..59c0b26241 100644
--- a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest.js
+++ b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest.js
@@ -18,6 +18,8 @@ const HTTP_SEARCH_STRING = "http prefix";
const HTTPS_SEARCH_STRING = "https prefix";
const PREFIX_SUGGESTIONS_STRIPPED_URL = "example.com/prefix-test";
+const ONE_CHAR_SEARCH_STRINGS = ["x", "x ", " x", " x "];
+
const { TIMESTAMP_TEMPLATE, TIMESTAMP_LENGTH } = QuickSuggest;
const TIMESTAMP_SEARCH_STRING = "timestamp";
const TIMESTAMP_SUGGESTION_URL = `http://example.com/timestamp-${TIMESTAMP_TEMPLATE}`;
@@ -69,6 +71,11 @@ const REMOTE_SETTINGS_RESULTS = [
iab_category: "22 - Shopping",
icon: "1234",
},
+ QuickSuggestTestUtils.ampRemoteSettings({
+ keywords: [...ONE_CHAR_SEARCH_STRINGS, "12", "a longer keyword"],
+ title: "Suggestion with 1-char keyword",
+ url: "http://example.com/1-char-keyword",
+ }),
];
function expectedNonSponsoredResult() {
@@ -751,10 +758,10 @@ async function doDedupeAgainstURLTest({
}
// Tests the remote settings latency histogram.
-add_task(
+add_tasks_with_rust(
{
// Not supported by the Rust backend.
- skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"),
+ skip_if_rust_enabled: true,
},
async function latencyTelemetry() {
UrlbarPrefs.set("suggest.quicksuggest.nonsponsored", true);
@@ -791,10 +798,10 @@ add_task(
// Tests setup and teardown of the remote settings client depending on whether
// quick suggest is enabled.
-add_task(
+add_tasks_with_rust(
{
// Not supported by the Rust backend.
- skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"),
+ skip_if_rust_enabled: true,
},
async function setupAndTeardown() {
Assert.ok(
@@ -885,7 +892,7 @@ add_task(
"Remote settings backend is disabled after enabling the Rust backend"
);
- UrlbarPrefs.clear("quicksuggest.rustEnabled");
+ UrlbarPrefs.set("quicksuggest.rustEnabled", false);
Assert.ok(
QuickSuggest.jsBackend.rs,
"Settings client is non-null after disabling the Rust backend"
@@ -898,6 +905,7 @@ add_task(
// Leave the prefs in the same state as when the task started.
UrlbarPrefs.clear("suggest.quicksuggest.nonsponsored");
UrlbarPrefs.clear("suggest.quicksuggest.sponsored");
+ UrlbarPrefs.clear("quicksuggest.rustEnabled");
UrlbarPrefs.set("quicksuggest.enabled", true);
Assert.ok(
!QuickSuggest.jsBackend.rs,
@@ -1349,10 +1357,10 @@ add_tasks_with_rust(async function block_timestamp() {
// Makes sure remote settings data is fetched using the correct `type` based on
// the value of the `quickSuggestRemoteSettingsDataType` Nimbus variable.
-add_task(
+add_tasks_with_rust(
{
// Not supported by the Rust backend.
- skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"),
+ skip_if_rust_enabled: true,
},
async function remoteSettingsDataType() {
UrlbarPrefs.set("suggest.quicksuggest.sponsored", true);
@@ -1509,7 +1517,7 @@ add_tasks_with_rust(async function tabToSearch() {
// search heuristic
makeSearchResult(context, {
engineName: Services.search.defaultEngine.name,
- engineIconUri: Services.search.defaultEngine.getIconURL(),
+ engineIconUri: await Services.search.defaultEngine.getIconURL(),
heuristic: true,
}),
// tab to search
@@ -1595,7 +1603,7 @@ add_tasks_with_rust(async function position() {
// search heuristic
makeSearchResult(context, {
engineName: Services.search.defaultEngine.name,
- engineIconUri: Services.search.defaultEngine.getIconURL(),
+ engineIconUri: await Services.search.defaultEngine.getIconURL(),
heuristic: true,
}),
// best match whose backing suggestion has a `position`
@@ -1659,3 +1667,35 @@ add_task(async function rustProviders() {
],
});
});
+
+// Tests the keyword/search-string-length threshold. Keywords/search strings
+// must be at least two characters long to be matched.
+add_tasks_with_rust(async function keywordLengthThreshold() {
+ UrlbarPrefs.set("suggest.quicksuggest.sponsored", true);
+ await QuickSuggestTestUtils.forceSync();
+
+ let tests = [
+ ...ONE_CHAR_SEARCH_STRINGS.map(keyword => ({ keyword, expected: false })),
+ { keyword: "12", expected: true },
+ { keyword: "a longer keyword", expected: true },
+ ];
+
+ for (let { keyword, expected } of tests) {
+ await check_results({
+ context: createContext(keyword, {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: !expected
+ ? []
+ : [
+ makeAmpResult({
+ keyword,
+ title: "Suggestion with 1-char keyword",
+ url: "http://example.com/1-char-keyword",
+ originalUrl: "http://example.com/1-char-keyword",
+ }),
+ ],
+ });
+ }
+});
diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js
index c17f3f1655..806685eff7 100644
--- a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js
+++ b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js
@@ -42,7 +42,7 @@ const REMOTE_SETTINGS_RESULTS = [
icon: "https://example.com/first-addon.svg",
title: "First Addon",
rating: "4.7",
- keywords: ["first", "1st", "two words", "a b c"],
+ keywords: ["first", "1st", "two words", "aa b c"],
description: "Description for the First Addon",
number_of_ratings: 1256,
score: 0.25,
@@ -353,35 +353,35 @@ add_tasks_with_rust(async function remoteSettings() {
}),
},
{
- input: "a",
+ input: "aa",
expected: makeExpectedResult({
suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
source: "remote-settings",
}),
},
{
- input: "a ",
+ input: "aa ",
expected: makeExpectedResult({
suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
source: "remote-settings",
}),
},
{
- input: "a b",
+ input: "aa b",
expected: makeExpectedResult({
suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
source: "remote-settings",
}),
},
{
- input: "a b ",
+ input: "aa b ",
expected: makeExpectedResult({
suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
source: "remote-settings",
}),
},
{
- input: "a b c",
+ input: "aa b c",
expected: makeExpectedResult({
suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
source: "remote-settings",
diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_pocket.js b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_pocket.js
index 29133a8579..79b4df2b77 100644
--- a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_pocket.js
+++ b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_pocket.js
@@ -214,9 +214,9 @@ add_tasks_with_rust(async function lowPrefixes() {
// starting at "how to" instead of the first word.
//
// Note: The Rust implementation doesn't support this.
-add_task(
+add_tasks_with_rust(
{
- skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"),
+ skip_if_rust_enabled: true,
},
async function lowPrefixes_howTo() {
// search string -> should match
diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_rust_ingest.js b/browser/components/urlbar/tests/quicksuggest/unit/test_rust_ingest.js
index e6ec61bcd4..f2e3f96c1f 100644
--- a/browser/components/urlbar/tests/quicksuggest/unit/test_rust_ingest.js
+++ b/browser/components/urlbar/tests/quicksuggest/unit/test_rust_ingest.js
@@ -78,11 +78,15 @@ add_task(async function firstRun() {
await checkSuggestions();
- // Disable and re-enable the backend. No new ingestion should start
- // immediately since this isn't the first time the backend has been enabled.
+ // Disable and re-enable the backend. Another ingest should start immediately
+ // since ingest is done every time the backend is re-enabled.
UrlbarPrefs.set("quicksuggest.rustEnabled", false);
UrlbarPrefs.set("quicksuggest.rustEnabled", true);
- await assertNoNewIngestStarted(ingestPromise);
+ ({ ingestPromise } = await waitForIngestStart(ingestPromise));
+
+ info("Awaiting ingest promise");
+ await ingestPromise;
+ info("Done awaiting ingest promise");
await checkSuggestions();
@@ -101,14 +105,18 @@ add_task(async function interval() {
"Sanity check: Rust backend is initially disabled"
);
- // Set a small interval and enable the backend. No new ingestion should start
- // immediately since this isn't the first time the backend has been enabled.
+ // Set a small interval and enable the backend. A new ingest will immediately
+ // start.
let intervalSecs = 1;
UrlbarPrefs.set("quicksuggest.rustIngestIntervalSeconds", intervalSecs);
UrlbarPrefs.set("quicksuggest.rustEnabled", true);
- await assertNoNewIngestStarted(ingestPromise);
+ ({ ingestPromise } = await waitForIngestStart(ingestPromise));
- // Wait for a few ingests to happen.
+ info("Awaiting ingest promise");
+ await ingestPromise;
+ info("Done awaiting ingest promise");
+
+ // Wait for a few ingests to happen due to the timer firing.
for (let i = 0; i < 3; i++) {
info("Preparing for ingest at index " + i);
@@ -193,17 +201,6 @@ async function waitForIngestStart(oldIngestPromise) {
return { ingestPromise: newIngestPromise };
}
-async function assertNoNewIngestStarted(oldIngestPromise) {
- for (let i = 0; i < 3; i++) {
- await TestUtils.waitForTick();
- }
- Assert.equal(
- QuickSuggest.rustBackend.ingestPromise,
- oldIngestPromise,
- "No new ingest started"
- );
-}
-
async function checkSuggestions(expected = [REMOTE_SETTINGS_SUGGESTION]) {
let actual = await QuickSuggest.rustBackend.query("amp");
Assert.deepEqual(
diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_weather.js b/browser/components/urlbar/tests/quicksuggest/unit/test_weather.js
index 28801904a1..cd794f435b 100644
--- a/browser/components/urlbar/tests/quicksuggest/unit/test_weather.js
+++ b/browser/components/urlbar/tests/quicksuggest/unit/test_weather.js
@@ -34,6 +34,15 @@ add_setup(async () => {
// `lastFetchTimeMs` is expected to be `fetchDelayAfterComingOnlineMs`, we can
// be sure the value actually came from `fetchDelayAfterComingOnlineMs`.
QuickSuggest.weather._test_fetchDelayAfterComingOnlineMs = 53;
+
+ // When `add_tasks_with_rust()` disables the Rust backend and forces sync, the
+ // JS backend will sync `Weather` with remote settings. Since keywords are
+ // present in remote settings at that point (we added them above), `Weather`
+ // will then start fetching. The fetch may or may not be done before our test
+ // task starts. To make sure it's done, queue another fetch and await it.
+ registerAddTasksWithRustSetup(async () => {
+ await QuickSuggest.weather._test_fetch();
+ });
});
// The feature should be properly uninitialized when it's disabled and then
@@ -52,17 +61,15 @@ add_tasks_with_rust(async function disableAndEnable_suggestPref() {
async function doBasicDisableAndEnableTest(pref) {
// Sanity check initial state.
- assertEnabled({
+ await assertEnabled({
message: "Sanity check initial state",
hasSuggestion: true,
- pendingFetchCount: 0,
});
// Disable the feature. It should be immediately uninitialized.
UrlbarPrefs.set(pref, false);
assertDisabled({
message: "After disabling",
- pendingFetchCount: 0,
});
// No suggestion should be returned for a search.
@@ -83,19 +90,17 @@ async function doBasicDisableAndEnableTest(pref) {
// Re-enable the feature. It should be immediately initialized and a fetch
// should start.
info("Re-enable the feature");
- let fetchPromise = QuickSuggest.weather.waitForFetches();
+ let fetchPromise = waitForNewWeatherFetch();
UrlbarPrefs.set(pref, true);
- assertEnabled({
+ await assertEnabled({
message: "Immediately after re-enabling",
hasSuggestion: false,
- pendingFetchCount: 1,
});
await fetchPromise;
- assertEnabled({
+ await assertEnabled({
message: "After awaiting fetch",
hasSuggestion: true,
- pendingFetchCount: 0,
});
Assert.equal(
@@ -126,16 +131,15 @@ async function doBasicDisableAndEnableTest(pref) {
// This task is only appropriate for the JS backend, not Rust, since fetching is
// always active with Rust.
-add_task(
+add_tasks_with_rust(
{
- skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"),
+ skip_if_rust_enabled: true,
},
async function keywordsNotDefined() {
// Sanity check initial state.
- assertEnabled({
+ await assertEnabled({
message: "Sanity check initial state",
hasSuggestion: true,
- pendingFetchCount: 0,
});
// Set RS data without any keywords. Fetching should immediately stop.
@@ -147,7 +151,6 @@ add_task(
]);
assertDisabled({
message: "After setting RS data without keywords",
- pendingFetchCount: 0,
});
// No suggestion should be returned for a search.
@@ -162,24 +165,22 @@ add_task(
// Set keywords. Fetching should immediately start.
info("Setting keywords");
- let fetchPromise = QuickSuggest.weather.waitForFetches();
+ let fetchPromise = waitForNewWeatherFetch();
await QuickSuggestTestUtils.setRemoteSettingsRecords([
{
type: "weather",
weather: MerinoTestUtils.WEATHER_RS_DATA,
},
]);
- assertEnabled({
+ await assertEnabled({
message: "Immediately after setting keywords",
hasSuggestion: false,
- pendingFetchCount: 1,
});
await fetchPromise;
- assertEnabled({
+ await assertEnabled({
message: "After awaiting fetch",
hasSuggestion: true,
- pendingFetchCount: 0,
});
Assert.equal(
@@ -211,27 +212,24 @@ add_task(
// it should be discarded since the feature is disabled.
add_tasks_with_rust(async function disableAndEnable_immediate1() {
// Sanity check initial state.
- assertEnabled({
+ await assertEnabled({
message: "Sanity check initial state",
hasSuggestion: true,
- pendingFetchCount: 0,
});
// Disable the feature. It should be immediately uninitialized.
UrlbarPrefs.set("weather.featureGate", false);
assertDisabled({
message: "After disabling",
- pendingFetchCount: 0,
});
// Re-enable the feature. It should be immediately initialized and a fetch
// should start.
- let fetchPromise = QuickSuggest.weather.waitForFetches();
+ let fetchPromise = waitForNewWeatherFetch();
UrlbarPrefs.set("weather.featureGate", true);
- assertEnabled({
+ await assertEnabled({
message: "Immediately after re-enabling",
hasSuggestion: false,
- pendingFetchCount: 1,
});
// Disable it again. The fetch will remain ongoing since pending fetches
@@ -239,7 +237,6 @@ add_tasks_with_rust(async function disableAndEnable_immediate1() {
UrlbarPrefs.set("weather.featureGate", false);
assertDisabled({
message: "After disabling again",
- pendingFetchCount: 1,
});
// Wait for the fetch to finish.
@@ -249,21 +246,19 @@ add_tasks_with_rust(async function disableAndEnable_immediate1() {
// uninitialized.
assertDisabled({
message: "After awaiting fetch",
- pendingFetchCount: 0,
});
// Clean up by re-enabling the feature for the remaining tasks.
- fetchPromise = QuickSuggest.weather.waitForFetches();
+ fetchPromise = waitForNewWeatherFetch();
UrlbarPrefs.set("weather.featureGate", true);
await fetchPromise;
// Wait for keywords to be re-synced from remote settings.
await QuickSuggestTestUtils.forceSync();
- assertEnabled({
+ await assertEnabled({
message: "On cleanup",
hasSuggestion: true,
- pendingFetchCount: 0,
});
});
@@ -279,26 +274,23 @@ add_tasks_with_rust(async function disableAndEnable_immediate1() {
// from step 2 should be discarded.
add_tasks_with_rust(async function disableAndEnable_immediate2() {
// Sanity check initial state.
- assertEnabled({
+ await assertEnabled({
message: "Sanity check initial state",
hasSuggestion: true,
- pendingFetchCount: 0,
});
// Disable the feature. It should be immediately uninitialized.
UrlbarPrefs.set("weather.featureGate", false);
assertDisabled({
message: "After disabling",
- pendingFetchCount: 0,
});
// Re-enable the feature. It should be immediately initialized and a fetch
// should start.
UrlbarPrefs.set("weather.featureGate", true);
- assertEnabled({
+ await assertEnabled({
message: "Immediately after re-enabling",
hasSuggestion: false,
- pendingFetchCount: 1,
});
// Disable it again. The fetch will remain ongoing since pending fetches
@@ -306,25 +298,21 @@ add_tasks_with_rust(async function disableAndEnable_immediate2() {
UrlbarPrefs.set("weather.featureGate", false);
assertDisabled({
message: "After disabling again",
- pendingFetchCount: 1,
});
- // Re-enable it. A new fetch should start, so now there will be two pending
- // fetches.
- let fetchPromise = QuickSuggest.weather.waitForFetches();
+ // Re-enable it. A new fetch should start.
+ let fetchPromise = waitForNewWeatherFetch();
UrlbarPrefs.set("weather.featureGate", true);
- assertEnabled({
+ await assertEnabled({
message: "Immediately after re-enabling again",
hasSuggestion: false,
- pendingFetchCount: 2,
});
- // Wait for both fetches to finish.
+ // Wait for it to finish.
await fetchPromise;
- assertEnabled({
+ await assertEnabled({
message: "Immediately after re-enabling again",
hasSuggestion: true,
- pendingFetchCount: 0,
});
// Wait for keywords to be re-synced from remote settings.
@@ -334,10 +322,9 @@ add_tasks_with_rust(async function disableAndEnable_immediate2() {
// A fetch that doesn't return a suggestion should cause the last-fetched
// suggestion to be discarded.
add_tasks_with_rust(async function noSuggestion() {
- assertEnabled({
+ await assertEnabled({
message: "Sanity check initial state",
hasSuggestion: true,
- pendingFetchCount: 0,
});
let histograms = MerinoTestUtils.getAndClearHistograms({
@@ -350,10 +337,9 @@ add_tasks_with_rust(async function noSuggestion() {
await QuickSuggest.weather._test_fetch();
- assertEnabled({
+ await assertEnabled({
message: "After fetch",
hasSuggestion: false,
- pendingFetchCount: 0,
});
Assert.equal(
QuickSuggest.weather._test_merino.lastFetchStatus,
@@ -381,19 +367,17 @@ add_tasks_with_rust(async function noSuggestion() {
// Clean up by forcing another fetch so the suggestion is non-null for the
// remaining tasks.
await QuickSuggest.weather._test_fetch();
- assertEnabled({
+ await assertEnabled({
message: "On cleanup",
hasSuggestion: true,
- pendingFetchCount: 0,
});
});
// A network error should cause the last-fetched suggestion to be discarded.
add_tasks_with_rust(async function networkError() {
- assertEnabled({
+ await assertEnabled({
message: "Sanity check initial state",
hasSuggestion: true,
- pendingFetchCount: 0,
});
let histograms = MerinoTestUtils.getAndClearHistograms({
@@ -411,10 +395,9 @@ add_tasks_with_rust(async function networkError() {
QuickSuggest.weather._test_setTimeoutMs(-1);
- assertEnabled({
+ await assertEnabled({
message: "After fetch",
hasSuggestion: false,
- pendingFetchCount: 0,
});
Assert.equal(
QuickSuggest.weather._test_merino.lastFetchStatus,
@@ -440,19 +423,17 @@ add_tasks_with_rust(async function networkError() {
// Clean up by forcing another fetch so the suggestion is non-null for the
// remaining tasks.
await QuickSuggest.weather._test_fetch();
- assertEnabled({
+ await assertEnabled({
message: "On cleanup",
hasSuggestion: true,
- pendingFetchCount: 0,
});
});
// An HTTP error should cause the last-fetched suggestion to be discarded.
add_tasks_with_rust(async function httpError() {
- assertEnabled({
+ await assertEnabled({
message: "Sanity check initial state",
hasSuggestion: true,
- pendingFetchCount: 0,
});
let histograms = MerinoTestUtils.getAndClearHistograms({
@@ -463,10 +444,9 @@ add_tasks_with_rust(async function httpError() {
MerinoTestUtils.server.response = { status: 500 };
await QuickSuggest.weather._test_fetch();
- assertEnabled({
+ await assertEnabled({
message: "After fetch",
hasSuggestion: false,
- pendingFetchCount: 0,
});
Assert.equal(
QuickSuggest.weather._test_merino.lastFetchStatus,
@@ -494,20 +474,18 @@ add_tasks_with_rust(async function httpError() {
MerinoTestUtils.server.reset();
MerinoTestUtils.server.response.body.suggestions = [WEATHER_SUGGESTION];
await QuickSuggest.weather._test_fetch();
- assertEnabled({
+ await assertEnabled({
message: "On cleanup",
hasSuggestion: true,
- pendingFetchCount: 0,
});
});
// A fetch that doesn't return a suggestion due to a client timeout should cause
// the last-fetched suggestion to be discarded.
add_tasks_with_rust(async function clientTimeout() {
- assertEnabled({
+ await assertEnabled({
message: "Sanity check initial state",
hasSuggestion: true,
- pendingFetchCount: 0,
});
let histograms = MerinoTestUtils.getAndClearHistograms({
@@ -528,10 +506,9 @@ add_tasks_with_rust(async function clientTimeout() {
await QuickSuggest.weather._test_fetch();
- assertEnabled({
+ await assertEnabled({
message: "After fetch",
hasSuggestion: false,
- pendingFetchCount: 0,
});
Assert.equal(
QuickSuggest.weather._test_merino.lastFetchStatus,
@@ -573,10 +550,9 @@ add_tasks_with_rust(async function clientTimeout() {
// Clean up by forcing another fetch so the suggestion is non-null for the
// remaining tasks.
await QuickSuggest.weather._test_fetch();
- assertEnabled({
+ await assertEnabled({
message: "On cleanup",
hasSuggestion: true,
- pendingFetchCount: 0,
});
});
@@ -662,10 +638,9 @@ async function doLocaleTest({ shouldRunTask, osUnit, unitsByLocale }) {
return;
}
- assertEnabled({
+ await assertEnabled({
message: "Sanity check initial state",
hasSuggestion: true,
- pendingFetchCount: 0,
});
// Sanity check initial locale info.
@@ -716,10 +691,9 @@ async function doLocaleTest({ shouldRunTask, osUnit, unitsByLocale }) {
// Blocks a result and makes sure the weather pref is disabled.
add_tasks_with_rust(async function block() {
// Sanity check initial state.
- assertEnabled({
+ await assertEnabled({
message: "Sanity check initial state",
hasSuggestion: true,
- pendingFetchCount: 0,
});
Assert.ok(
UrlbarPrefs.get("suggest.weather"),
@@ -775,17 +749,16 @@ add_tasks_with_rust(async function block() {
});
// Re-enable the pref and clean up.
- let fetchPromise = QuickSuggest.weather.waitForFetches();
+ let fetchPromise = waitForNewWeatherFetch();
UrlbarPrefs.set("suggest.weather", true);
await fetchPromise;
// Wait for keywords to be re-synced from remote settings.
await QuickSuggestTestUtils.forceSync();
- assertEnabled({
+ await assertEnabled({
message: "On cleanup",
hasSuggestion: true,
- pendingFetchCount: 0,
});
});
@@ -849,16 +822,12 @@ async function doWakeTest({
// Advance the clock and simulate wake.
info("Sending wake notification");
+ let fetchPromise = waitForNewWeatherFetch();
let nowOnWake = nowOnStart + sleepIntervalMs;
dateNowStub.returns(nowOnWake);
QuickSuggest.weather.observe(null, "wake_notification", "");
Assert.equal(
- QuickSuggest.weather._test_pendingFetchCount,
- 0,
- "After wake, next fetch should not have immediately started"
- );
- Assert.equal(
QuickSuggest.weather._test_lastFetchTimeMs,
nowOnStart,
"After wake, last fetch time should be unchanged"
@@ -891,18 +860,13 @@ async function doWakeTest({
// Wait for the fetch. If the wake didn't trigger it, then the caller should
// have passed in a `sleepIntervalMs` that will make it start soon.
info("Waiting for fetch after wake");
- await QuickSuggest.weather.waitForFetches();
+ await fetchPromise;
Assert.equal(
QuickSuggest.weather._test_fetchTimerMs,
QuickSuggest.weather._test_fetchIntervalMs,
"After post-wake fetch, timer period should remain full fetch interval"
);
- Assert.equal(
- QuickSuggest.weather._test_pendingFetchCount,
- 0,
- "After post-wake fetch, no more fetches should be pending"
- );
dateNowStub.restore();
}
@@ -958,11 +922,6 @@ async function doOnlineTestWithSuggestion({ topic, dataValues }) {
QuickSuggest.weather.observe(null, topic, data);
Assert.equal(
- QuickSuggest.weather._test_pendingFetchCount,
- 0,
- "Fetch should not have started"
- );
- Assert.equal(
QuickSuggest.weather._test_fetchTimer,
timer,
"Timer should not have been recreated"
@@ -1033,11 +992,6 @@ async function doOnlineTestWithNullSuggestion({
"Suggestion should remain null"
);
Assert.equal(
- QuickSuggest.weather._test_pendingFetchCount,
- 0,
- "Fetch should not have started"
- );
- Assert.equal(
QuickSuggest.weather._test_fetchTimer,
timer,
"Timer should not have been recreated"
@@ -1055,13 +1009,9 @@ async function doOnlineTestWithNullSuggestion({
Assert.ok(!QuickSuggest.weather.suggestion, "Suggestion should be null");
info("Sending notification: " + JSON.stringify({ topic, data }));
+ let fetchPromise = waitForNewWeatherFetch();
QuickSuggest.weather.observe(null, topic, data);
- Assert.equal(
- QuickSuggest.weather._test_pendingFetchCount,
- 0,
- "Fetch should not have started yet"
- );
Assert.notEqual(
QuickSuggest.weather._test_fetchTimer,
0,
@@ -1081,13 +1031,8 @@ async function doOnlineTestWithNullSuggestion({
timer = QuickSuggest.weather._test_fetchTimer;
info("Waiting for fetch after notification");
- await QuickSuggest.weather.waitForFetches();
+ await fetchPromise;
- Assert.equal(
- QuickSuggest.weather._test_pendingFetchCount,
- 0,
- "Fetch should not be pending"
- );
Assert.notEqual(
QuickSuggest.weather._test_fetchTimer,
0,
@@ -1164,20 +1109,23 @@ async function doManyNotificationsTest(notifications) {
MerinoTestUtils.WEATHER_SUGGESTION,
];
+ let { fetchPromise: oldFetchPromise } = QuickSuggest.weather;
+ let fetchPromise = waitForNewWeatherFetch();
+
// Send the notifications.
for (let [topic, data] of notifications) {
info("Sending notification: " + JSON.stringify({ topic, data }));
QuickSuggest.weather.observe(null, topic, data);
+ Assert.equal(
+ QuickSuggest.weather.fetchPromise,
+ oldFetchPromise,
+ "No new fetch should have started yet"
+ );
}
info("Waiting for fetch after notifications");
- await QuickSuggest.weather.waitForFetches();
+ await fetchPromise;
- Assert.equal(
- QuickSuggest.weather._test_pendingFetchCount,
- 0,
- "Fetch should not be pending"
- );
Assert.notEqual(
QuickSuggest.weather._test_fetchTimer,
0,
@@ -1241,7 +1189,7 @@ add_tasks_with_rust(async function vpn() {
// Simulate the link status changing. Since the mock link service still
// indicates a VPN is detected, the suggestion should remain null.
- let fetchPromise = QuickSuggest.weather.waitForFetches();
+ let fetchPromise = waitForNewWeatherFetch();
QuickSuggest.weather.observe(null, "network:link-status-changed", "changed");
await fetchPromise;
Assert.ok(!QuickSuggest.weather.suggestion, "Suggestion should remain null");
@@ -1251,7 +1199,7 @@ add_tasks_with_rust(async function vpn() {
Ci.nsINetworkLinkService.NONE_DETECTED;
// Simulate the link status changing again. The suggestion should be fetched.
- fetchPromise = QuickSuggest.weather.waitForFetches();
+ fetchPromise = waitForNewWeatherFetch();
QuickSuggest.weather.observe(null, "network:link-status-changed", "changed");
await fetchPromise;
Assert.ok(QuickSuggest.weather.suggestion, "Suggestion should be fetched");
@@ -1264,10 +1212,9 @@ add_tasks_with_rust(async function vpn() {
// weather record.
add_tasks_with_rust(async function nimbusOverride() {
// Sanity check initial state.
- assertEnabled({
+ await assertEnabled({
message: "Sanity check initial state",
hasSuggestion: true,
- pendingFetchCount: 0,
});
let defaultResult = makeWeatherResult();
@@ -1349,7 +1296,7 @@ add_tasks_with_rust(async function nimbusOverride() {
});
});
-function assertEnabled({ message, hasSuggestion, pendingFetchCount }) {
+async function assertEnabled({ message, hasSuggestion }) {
info("Asserting feature is enabled");
if (message) {
info(message);
@@ -1360,20 +1307,20 @@ function assertEnabled({ message, hasSuggestion, pendingFetchCount }) {
hasSuggestion,
"Suggestion is null or non-null as expected"
);
+ Assert.ok(QuickSuggest.weather._test_merino, "Merino client is non-null");
+
+ await TestUtils.waitForCondition(
+ () => QuickSuggest.weather._test_fetchTimer,
+ "Waiting for fetch timer to become non-zero"
+ );
Assert.notEqual(
QuickSuggest.weather._test_fetchTimer,
0,
"Fetch timer is non-zero"
);
- Assert.ok(QuickSuggest.weather._test_merino, "Merino client is non-null");
- Assert.equal(
- QuickSuggest.weather._test_pendingFetchCount,
- pendingFetchCount,
- "Expected pending fetch count"
- );
}
-function assertDisabled({ message, pendingFetchCount }) {
+function assertDisabled({ message }) {
info("Asserting feature is disabled");
if (message) {
info(message);
@@ -1394,9 +1341,4 @@ function assertDisabled({ message, pendingFetchCount }) {
null,
"Merino client is null"
);
- Assert.equal(
- QuickSuggest.weather._test_pendingFetchCount,
- pendingFetchCount,
- "Expected pending fetch count"
- );
}
diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_weather_keywords.js b/browser/components/urlbar/tests/quicksuggest/unit/test_weather_keywords.js
index efa5922c3e..559e0cc1fa 100644
--- a/browser/components/urlbar/tests/quicksuggest/unit/test_weather_keywords.js
+++ b/browser/components/urlbar/tests/quicksuggest/unit/test_weather_keywords.js
@@ -23,6 +23,15 @@ add_setup(async () => {
prefs: [["suggest.quicksuggest.nonsponsored", true]],
});
await MerinoTestUtils.initWeather();
+
+ // When `add_tasks_with_rust()` disables the Rust backend and forces sync, the
+ // JS backend will sync `Weather` with remote settings. Since keywords are
+ // present in remote settings at that point (we added them above), `Weather`
+ // will then start fetching. The fetch may or may not be done before our test
+ // task starts. To make sure it's done, queue another fetch and await it.
+ registerAddTasksWithRustSetup(async () => {
+ await QuickSuggest.weather._test_fetch();
+ });
});
// * Settings data: none
@@ -89,9 +98,9 @@ add_tasks_with_rust(async function () {
//
// JS backend only. The Rust component expects settings data to contain
// min_keyword_length.
-add_task(
+add_tasks_with_rust(
{
- skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"),
+ skip_if_rust_enabled: true,
},
async function () {
await doKeywordsTest({
@@ -128,9 +137,9 @@ add_task(
//
// JS backend only. The Rust component doesn't treat minKeywordLength == 0 as a
// special case.
-add_task(
+add_tasks_with_rust(
{
- skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"),
+ skip_if_rust_enabled: true,
},
async function () {
await doKeywordsTest({
@@ -296,9 +305,9 @@ add_tasks_with_rust(async function () {
//
// JS backend only. The Rust component expects settings data to contain
// min_keyword_length.
-add_task(
+add_tasks_with_rust(
{
- skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"),
+ skip_if_rust_enabled: true,
},
async function () {
await doKeywordsTest({
@@ -338,9 +347,9 @@ add_task(
//
// JS backend only. The Rust component doesn't treat minKeywordLength == 0 as a
// special case.
-add_task(
+add_tasks_with_rust(
{
- skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"),
+ skip_if_rust_enabled: true,
},
async function () {
await doKeywordsTest({
@@ -578,9 +587,9 @@ add_tasks_with_rust(async function () {
// TODO bug 1879209: This doesn't work with the Rust backend because if
// min_keyword_length isn't specified on ingest, the Rust database will retain
// the last known good min_keyword_length, which interferes with this task.
-add_task(
+add_tasks_with_rust(
{
- skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"),
+ skip_if_rust_enabled: true,
},
async function () {
await doKeywordsTest({
@@ -618,9 +627,9 @@ add_task(
// TODO bug 1879209: This doesn't work with the Rust backend because if
// min_keyword_length isn't specified on ingest, the Rust database will retain
// the last known good min_keyword_length, which interferes with this task.
-add_task(
+add_tasks_with_rust(
{
- skip_if: () => UrlbarPrefs.get("quickSuggestRustEnabled"),
+ skip_if_rust_enabled: true,
},
async function () {
await doKeywordsTest({
@@ -817,7 +826,7 @@ async function doKeywordsTest({
!UrlbarPrefs.get("quickSuggestRustEnabled") &&
(nimbusValues?.weatherKeywords || settingsData?.keywords)
) {
- fetchPromise = QuickSuggest.weather.waitForFetches();
+ fetchPromise = waitForNewWeatherFetch();
}
let nimbusCleanup;
@@ -838,7 +847,6 @@ async function doKeywordsTest({
if (fetchPromise) {
info("Waiting for fetch");
- assertFetchingStarted({ pendingFetchCount: 1 });
await fetchPromise;
info("Got fetch");
}
@@ -872,10 +880,10 @@ async function doKeywordsTest({
await nimbusCleanup?.();
- fetchPromise = null;
if (!QuickSuggest.weather.suggestion) {
- fetchPromise = QuickSuggest.weather.waitForFetches();
+ fetchPromise = waitForNewWeatherFetch();
}
+
await QuickSuggestTestUtils.setRemoteSettingsRecords([
{
type: "weather",
@@ -905,28 +913,8 @@ async function doMatchingQuickSuggestTest(pref, isSponsored) {
let keyword = "test";
let attachment = isSponsored
- ? {
- id: 1,
- url: "http://example.com/amp",
- title: "AMP Suggestion",
- keywords: [keyword],
- click_url: "http://example.com/amp-click",
- impression_url: "http://example.com/amp-impression",
- advertiser: "Amp",
- iab_category: "22 - Shopping",
- icon: "1234",
- }
- : {
- id: 2,
- url: "http://example.com/wikipedia",
- title: "Wikipedia Suggestion",
- keywords: [keyword],
- click_url: "http://example.com/wikipedia-click",
- impression_url: "http://example.com/wikipedia-impression",
- advertiser: "Wikipedia",
- iab_category: "5 - Education",
- icon: "1234",
- };
+ ? QuickSuggestTestUtils.ampRemoteSettings({ keywords: [keyword] })
+ : QuickSuggestTestUtils.wikipediaRemoteSettings({ keywords: [keyword] });
// Add a remote settings result to quick suggest.
let oldPrefValue = UrlbarPrefs.get(pref);
@@ -943,27 +931,6 @@ async function doMatchingQuickSuggestTest(pref, isSponsored) {
]);
// First do a search to verify the quick suggest result matches the keyword.
- let payload;
- if (!UrlbarPrefs.get("quickSuggestRustEnabled")) {
- payload = {
- source: "remote-settings",
- provider: "AdmWikipedia",
- sponsoredImpressionUrl: attachment.impression_url,
- sponsoredClickUrl: attachment.click_url,
- sponsoredBlockId: attachment.id,
- };
- } else {
- payload = {
- source: "rust",
- provider: isSponsored ? "Amp" : "Wikipedia",
- };
- if (isSponsored) {
- payload.sponsoredImpressionUrl = attachment.impression_url;
- payload.sponsoredClickUrl = attachment.click_url;
- payload.sponsoredBlockId = attachment.id;
- }
- }
-
info("Doing first search for quick suggest result");
await check_results({
context: createContext(keyword, {
@@ -971,35 +938,9 @@ async function doMatchingQuickSuggestTest(pref, isSponsored) {
isPrivate: false,
}),
matches: [
- {
- type: UrlbarUtils.RESULT_TYPE.URL,
- source: UrlbarUtils.RESULT_SOURCE.SEARCH,
- heuristic: false,
- payload: {
- ...payload,
- telemetryType: isSponsored ? "adm_sponsored" : "adm_nonsponsored",
- qsSuggestion: keyword,
- title: attachment.title,
- url: attachment.url,
- displayUrl: attachment.url.replace(/[/]$/, ""),
- originalUrl: attachment.url,
- icon: null,
- sponsoredAdvertiser: attachment.advertiser,
- sponsoredIabCategory: attachment.iab_category,
- isSponsored,
- descriptionL10n: isSponsored
- ? { id: "urlbar-result-action-sponsored" }
- : undefined,
- helpUrl: QuickSuggest.HELP_URL,
- helpL10n: {
- id: "urlbar-result-menu-learn-more-about-firefox-suggest",
- },
- isBlockable: true,
- blockL10n: {
- id: "urlbar-result-menu-dismiss-firefox-suggest",
- },
- },
- },
+ isSponsored
+ ? makeAmpResult({ keyword })
+ : makeWikipediaResult({ keyword }),
],
});
@@ -1398,7 +1339,7 @@ async function doIncrementTest({
!UrlbarPrefs.get("quickSuggestRustEnabled") &&
(nimbusValues?.weatherKeywords || settingsData?.weather?.keywords)
) {
- fetchPromise = QuickSuggest.weather.waitForFetches();
+ fetchPromise = waitForNewWeatherFetch();
}
let nimbusCleanup;
@@ -1419,7 +1360,6 @@ async function doIncrementTest({
if (fetchPromise) {
info("Waiting for fetch");
- assertFetchingStarted({ pendingFetchCount: 1 });
await fetchPromise;
info("Got fetch");
}
@@ -1472,9 +1412,8 @@ async function doIncrementTest({
await nimbusCleanup?.();
- fetchPromise = null;
if (!QuickSuggest.weather.suggestion) {
- fetchPromise = QuickSuggest.weather.waitForFetches();
+ fetchPromise = waitForNewWeatherFetch();
}
await QuickSuggestTestUtils.setRemoteSettingsRecords([
{
@@ -1485,19 +1424,3 @@ async function doIncrementTest({
UrlbarPrefs.clear("weather.minKeywordLength");
await fetchPromise;
}
-
-function assertFetchingStarted() {
- info("Asserting fetching has started");
-
- Assert.notEqual(
- QuickSuggest.weather._test_fetchTimer,
- 0,
- "Fetch timer is non-zero"
- );
- Assert.ok(QuickSuggest.weather._test_merino, "Merino client is non-null");
- Assert.equal(
- QuickSuggest.weather._test_pendingFetchCount,
- 1,
- "Expected pending fetch count"
- );
-}
diff --git a/browser/components/urlbar/tests/quicksuggest/unit/xpcshell.toml b/browser/components/urlbar/tests/quicksuggest/unit/xpcshell.toml
index ceab478795..1f0e226684 100644
--- a/browser/components/urlbar/tests/quicksuggest/unit/xpcshell.toml
+++ b/browser/components/urlbar/tests/quicksuggest/unit/xpcshell.toml
@@ -49,3 +49,4 @@ skip-if = ["true"] # Bug 1880214
["test_weather.js"]
["test_weather_keywords.js"]
+skip-if = ["verify"] # Bug 1880214 - Takes a very long time due to add_tasks_with_rust()