summaryrefslogtreecommitdiffstats
path: root/toolkit/components/search/tests/xpcshell/test_engine_selector_remote_settings.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /toolkit/components/search/tests/xpcshell/test_engine_selector_remote_settings.js
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/search/tests/xpcshell/test_engine_selector_remote_settings.js')
-rw-r--r--toolkit/components/search/tests/xpcshell/test_engine_selector_remote_settings.js343
1 files changed, 343 insertions, 0 deletions
diff --git a/toolkit/components/search/tests/xpcshell/test_engine_selector_remote_settings.js b/toolkit/components/search/tests/xpcshell/test_engine_selector_remote_settings.js
new file mode 100644
index 0000000000..336ffb1ee5
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/test_engine_selector_remote_settings.js
@@ -0,0 +1,343 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ PromiseUtils: "resource://gre/modules/PromiseUtils.sys.mjs",
+ SearchEngineSelector: "resource://gre/modules/SearchEngineSelector.sys.mjs",
+});
+
+const TEST_CONFIG = [
+ {
+ engineName: "aol",
+ orderHint: 500,
+ webExtension: {
+ locales: ["default"],
+ },
+ appliesTo: [
+ {
+ included: { everywhere: true },
+ },
+ {
+ included: { regions: ["us"] },
+ webExtension: {
+ locales: ["$USER_LOCALE"],
+ },
+ },
+ ],
+ },
+ {
+ engineName: "lycos",
+ orderHint: 1000,
+ default: "yes",
+ appliesTo: [
+ {
+ included: { everywhere: true },
+ excluded: { locales: { matches: ["zh-CN"] } },
+ },
+ ],
+ },
+ {
+ engineName: "altavista",
+ orderHint: 2000,
+ defaultPrivate: "yes",
+ appliesTo: [
+ {
+ included: { locales: { matches: ["en-US"] } },
+ },
+ {
+ included: { regions: ["default"] },
+ },
+ ],
+ },
+ {
+ engineName: "excite",
+ default: "yes-if-no-other",
+ appliesTo: [
+ {
+ included: { everywhere: true },
+ excluded: { regions: ["us"] },
+ },
+ {
+ included: { everywhere: true },
+ cohort: "acohortid",
+ },
+ ],
+ },
+ {
+ engineName: "askjeeves",
+ },
+];
+
+let getStub;
+
+add_task(async function setup() {
+ const searchConfigSettings = await RemoteSettings(SearchUtils.SETTINGS_KEY);
+ getStub = sinon.stub(searchConfigSettings, "get");
+
+ // We expect this error from remove settings as we're invalidating the
+ // signature.
+ consoleAllowList.push("Invalid content signature (abc)");
+ // We also test returning an empty configuration.
+ consoleAllowList.push("Received empty search configuration");
+});
+
+add_task(async function test_selector_basic_get() {
+ const listenerSpy = sinon.spy();
+ const engineSelector = new SearchEngineSelector(listenerSpy);
+ getStub.onFirstCall().returns(TEST_CONFIG);
+
+ const { engines } = await engineSelector.fetchEngineConfiguration({
+ locale: "en-US",
+ region: "default",
+ });
+
+ Assert.deepEqual(
+ engines.map(e => e.engineName),
+ ["lycos", "altavista", "aol", "excite"],
+ "Should have obtained the correct data from the database."
+ );
+ Assert.ok(listenerSpy.notCalled, "Should not have called the listener");
+});
+
+add_task(async function test_selector_get_reentry() {
+ const listenerSpy = sinon.spy();
+ const engineSelector = new SearchEngineSelector(listenerSpy);
+ let promise = PromiseUtils.defer();
+ getStub.resetHistory();
+ getStub.onFirstCall().returns(promise.promise);
+ delete engineSelector._configuration;
+
+ let firstResult;
+ let secondResult;
+
+ const firstCallPromise = engineSelector
+ .fetchEngineConfiguration({
+ locale: "en-US",
+ region: "default",
+ })
+ .then(result => (firstResult = result.engines));
+
+ const secondCallPromise = engineSelector
+ .fetchEngineConfiguration({
+ locale: "en-US",
+ region: "default",
+ })
+ .then(result => (secondResult = result.engines));
+
+ Assert.strictEqual(
+ firstResult,
+ undefined,
+ "Should not have returned the first result yet."
+ );
+
+ Assert.strictEqual(
+ secondResult,
+ undefined,
+ "Should not have returned the second result yet."
+ );
+
+ promise.resolve(TEST_CONFIG);
+
+ await Promise.all([firstCallPromise, secondCallPromise]);
+ Assert.deepEqual(
+ firstResult.map(e => e.engineName),
+ ["lycos", "altavista", "aol", "excite"],
+ "Should have returned the correct data to the first call"
+ );
+
+ Assert.deepEqual(
+ secondResult.map(e => e.engineName),
+ ["lycos", "altavista", "aol", "excite"],
+ "Should have returned the correct data to the second call"
+ );
+ Assert.ok(listenerSpy.notCalled, "Should not have called the listener");
+});
+
+add_task(async function test_selector_config_update() {
+ const listenerSpy = sinon.spy();
+ const engineSelector = new SearchEngineSelector(listenerSpy);
+ getStub.resetHistory();
+ getStub.onFirstCall().returns(TEST_CONFIG);
+
+ const { engines } = await engineSelector.fetchEngineConfiguration({
+ locale: "en-US",
+ region: "default",
+ });
+
+ Assert.deepEqual(
+ engines.map(e => e.engineName),
+ ["lycos", "altavista", "aol", "excite"],
+ "Should have got the correct configuration"
+ );
+
+ Assert.ok(listenerSpy.notCalled, "Should not have called the listener yet");
+
+ const NEW_DATA = [
+ {
+ default: "yes",
+ engineName: "askjeeves",
+ appliesTo: [{ included: { everywhere: true } }],
+ schema: 1553857697843,
+ last_modified: 1553859483588,
+ },
+ ];
+
+ getStub.resetHistory();
+ getStub.onFirstCall().returns(NEW_DATA);
+ await RemoteSettings(SearchUtils.SETTINGS_KEY).emit("sync", {
+ data: {
+ current: NEW_DATA,
+ },
+ });
+
+ Assert.ok(listenerSpy.called, "Should have called the listener");
+
+ const result = await engineSelector.fetchEngineConfiguration({
+ locale: "en-US",
+ region: "default",
+ });
+
+ Assert.deepEqual(
+ result.engines.map(e => e.engineName),
+ ["askjeeves"],
+ "Should have updated the configuration with the new data"
+ );
+});
+
+add_task(async function test_selector_db_modification() {
+ const engineSelector = new SearchEngineSelector();
+ // Fill the database with some values that we can use to test that it is cleared.
+ const db = RemoteSettings(SearchUtils.SETTINGS_KEY).db;
+ await db.importChanges(
+ {},
+ Date.now(),
+ [
+ {
+ id: "85e1f268-9ca5-4b52-a4ac-922df5c07264",
+ default: "yes",
+ engineName: "askjeeves",
+ appliesTo: [{ included: { everywhere: true } }],
+ },
+ ],
+ { clear: true }
+ );
+
+ // Stub the get() so that the first call simulates a signature error, and
+ // the second simulates success reading from the dump.
+ getStub.resetHistory();
+ getStub
+ .onFirstCall()
+ .rejects(new RemoteSettingsClient.InvalidSignatureError("abc"));
+ getStub.onSecondCall().returns(TEST_CONFIG);
+
+ let result = await engineSelector.fetchEngineConfiguration({
+ locale: "en-US",
+ region: "default",
+ });
+
+ Assert.ok(
+ getStub.calledTwice,
+ "Should have called the get() function twice."
+ );
+
+ const databaseEntries = await db.list();
+ Assert.equal(databaseEntries.length, 0, "Should have cleared the database.");
+
+ Assert.deepEqual(
+ result.engines.map(e => e.engineName),
+ ["lycos", "altavista", "aol", "excite"],
+ "Should have returned the correct data."
+ );
+});
+
+add_task(async function test_selector_db_modification_never_succeeds() {
+ const engineSelector = new SearchEngineSelector();
+ // Fill the database with some values that we can use to test that it is cleared.
+ const db = RemoteSettings(SearchUtils.SETTINGS_KEY).db;
+ await db.importChanges(
+ {},
+ Date.now(),
+ [
+ {
+ id: "b70edfdd-1c3f-4b7b-ab55-38cb048636c0",
+ default: "yes",
+ engineName: "askjeeves",
+ appliesTo: [{ included: { everywhere: true } }],
+ },
+ ],
+ {
+ clear: true,
+ }
+ );
+
+ // Now simulate the condition where for some reason we never get a
+ // valid result.
+ getStub.reset();
+ getStub.rejects(new RemoteSettingsClient.InvalidSignatureError("abc"));
+
+ await Assert.rejects(
+ engineSelector.fetchEngineConfiguration({
+ locale: "en-US",
+ region: "default",
+ }),
+ ex => ex.result == Cr.NS_ERROR_UNEXPECTED,
+ "Should have rejected loading the engine configuration"
+ );
+
+ Assert.ok(
+ getStub.calledTwice,
+ "Should have called the get() function twice."
+ );
+
+ const databaseEntries = await db.list();
+ Assert.equal(databaseEntries.length, 0, "Should have cleared the database.");
+});
+
+add_task(async function test_empty_results() {
+ // Check that returning an empty result re-tries.
+ const engineSelector = new SearchEngineSelector();
+ // Fill the database with some values that we can use to test that it is cleared.
+ const db = RemoteSettings(SearchUtils.SETTINGS_KEY).db;
+ await db.importChanges(
+ {},
+ Date.now(),
+ [
+ {
+ id: "df5655ca-e045-4f8c-a7ee-047eeb654722",
+ default: "yes",
+ engineName: "askjeeves",
+ appliesTo: [{ included: { everywhere: true } }],
+ },
+ ],
+ {
+ clear: true,
+ }
+ );
+
+ // Stub the get() so that the first call simulates an empty database, and
+ // the second simulates success reading from the dump.
+ getStub.resetHistory();
+ getStub.onFirstCall().returns([]);
+ getStub.onSecondCall().returns(TEST_CONFIG);
+
+ let result = await engineSelector.fetchEngineConfiguration({
+ locale: "en-US",
+ region: "default",
+ });
+
+ Assert.ok(
+ getStub.calledTwice,
+ "Should have called the get() function twice."
+ );
+
+ const databaseEntries = await db.list();
+ Assert.equal(databaseEntries.length, 0, "Should have cleared the database.");
+
+ Assert.deepEqual(
+ result.engines.map(e => e.engineName),
+ ["lycos", "altavista", "aol", "excite"],
+ "Should have returned the correct data."
+ );
+});