/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; const CONFIG_V2 = [ { identifier: "engine_to_remove" }, { identifier: "engine_to_keep" }, { specificDefaults: [ { default: "engine_to_remove", environment: { excludedRegions: ["FR"] }, }, { default: "engine_to_keep", environment: { regions: ["FR"] }, }, ], }, ]; const CONFIG_V2_UPDATED = [ { identifier: "engine_to_keep" }, { specificDefaults: [ { default: "engine_to_remove", environment: { excludedRegions: ["FR"] }, }, { default: "engine_to_keep", environment: { regions: ["FR"] }, }, ], }, ]; let stub; let settingsFilePath; let userSettings; add_setup(async function () { SearchSettings.SETTINGS_INVALIDATION_DELAY = 100; SearchTestUtils.useMockIdleService(); SearchTestUtils.setRemoteSettingsConfig(CONFIG_V2); stub = sinon.stub( await SearchService, "_showRemovalOfSearchEngineNotificationBox" ); settingsFilePath = PathUtils.join(PathUtils.profileDir, SETTINGS_FILENAME); Region._setHomeRegion("", false); let promiseSaved = promiseAfterSettings(); await SearchService.init(); await promiseSaved; userSettings = await SearchService._settings.get(); registerCleanupFunction(async () => { sinon.restore(); }); }); // Verify the loaded configuration matches what we expect for the test. add_task(async function test_initial_config_correct() { const installedEngines = await SearchService.getAppProvidedEngines(); Assert.deepEqual( installedEngines.map(e => e.id), ["engine_to_remove", "engine_to_keep"], "Should have the correct list of engines installed." ); Assert.equal( (await SearchService.getDefault()).id, "engine_to_remove", "Should have loaded the expected default engine" ); }); add_task(async function test_metadata_undefined() { let defaultEngineChanged = SearchTestUtils.promiseSearchNotification( SearchUtils.MODIFIED_TYPE.DEFAULT, SearchUtils.TOPIC_ENGINE_MODIFIED ); info("Update region to FR."); Region._setHomeRegion("FR", false); let settings = structuredClone(userSettings); settings.metaData = undefined; await reloadEngines(settings); Assert.ok( stub.notCalled, "_reloadEngines should not have shown the notification box." ); settings = structuredClone(userSettings); settings.metaData = undefined; await loadEngines(settings); Assert.ok( stub.notCalled, "_loadEngines should not have shown the notification box." ); const newDefault = await defaultEngineChanged; Assert.equal( newDefault.name, "engine_to_keep", "Should have correctly notified the new default engine." ); }); add_task(async function test_metadata_changed() { let metaDataProperties = [ "locale", "region", "channel", "experiment", "distroID", ]; for (let name of metaDataProperties) { let settings = structuredClone(userSettings); settings.metaData[name] = "test"; await assert_metadata_changed(settings); } }); add_task(async function test_default_engine_unchanged() { let currentEngineName = SearchService._getEngineDefault(false).name; Assert.equal( currentEngineName, "engine_to_remove", "Default engine should be unchanged." ); await reloadEngines(structuredClone(userSettings)); Assert.ok( stub.notCalled, "_reloadEngines should not have shown the notification box." ); await loadEngines(structuredClone(userSettings)); Assert.ok( stub.notCalled, "_loadEngines should not have shown the notification box." ); }); add_task(async function test_new_current_engine_is_undefined() { consoleAllowList.push("No default engine"); let settings = structuredClone(userSettings); let getEngineDefaultStub = sinon.stub( await SearchService, "_getEngineDefault" ); getEngineDefaultStub.returns(undefined); await loadEngines(settings); Assert.ok( stub.notCalled, "_loadEngines should not have shown the notification box." ); getEngineDefaultStub.restore(); }); add_task(async function test_current_engine_is_null() { SearchService._currentEngine = null; await reloadEngines(structuredClone(userSettings)); Assert.ok( stub.notCalled, "_reloadEngines should not have shown the notification box." ); let settings = structuredClone(userSettings); settings.metaData.current = null; await loadEngines(settings); Assert.ok( stub.notCalled, "_loadEngines should not have shown the notification box." ); }); add_task(async function test_default_changed_and_metadata_unchanged_exists() { info("Update region to FR to change engine."); Region._setHomeRegion("FR", false); info("Set user settings metadata to the same properties as cached metadata."); await SearchService._fetchEngineSelectorEngines(); userSettings.metaData = { ...SearchService._settings.getSettingsMetaData(), appDefaultEngine: "engine_to_remove", }; await reloadEngines(structuredClone(userSettings)); Assert.ok( stub.notCalled, "_reloadEngines should not show the notification box as the engine still exists." ); // Reset. Region._setHomeRegion("US", false); await reloadEngines(structuredClone(userSettings)); }); add_task(async function test_default_engine_changed_and_metadata_unchanged() { info("Update region to FR to change engine."); Region._setHomeRegion("FR", false); const defaultEngineChanged = SearchTestUtils.promiseSearchNotification( SearchUtils.MODIFIED_TYPE.DEFAULT, SearchUtils.TOPIC_ENGINE_MODIFIED ); info("Set user settings metadata to the same properties as cached metadata."); await SearchService._fetchEngineSelectorEngines(); userSettings.metaData = { ...SearchService._settings.getSettingsMetaData(), appDefaultEngineId: "engine_to_remove", }; // Update config by removing the app default engine await setConfigToLoad(CONFIG_V2_UPDATED); await reloadEngines(structuredClone(userSettings)); Assert.ok( stub.calledOnce, "_reloadEngines should show the notification box." ); Assert.deepEqual( stub.firstCall.args, ["engine_to_remove", "engine_to_keep"], "_showRemovalOfSearchEngineNotificationBox should display " + "'engine_to_remove' as the engine removed and 'engine_to_keep' as the new " + "default engine." ); const newDefault = await defaultEngineChanged; Assert.equal( newDefault.name, "engine_to_keep", "Should have correctly notified the new default engine" ); info("Reset userSettings.metaData.current engine."); let settings = structuredClone(userSettings); settings.metaData.current = SearchService._currentEngine; await loadEngines(settings); Assert.ok(stub.calledTwice, "_loadEngines should show the notification box."); Assert.deepEqual( stub.secondCall.args, ["engine_to_remove", "engine_to_keep"], "_showRemovalOfSearchEngineNotificationBox should display " + "'engine_to_remove' as the engine removed and 'engine_to_keep' as the new " + "default engine." ); }); add_task(async function test_app_default_engine_changed_on_start_up() { let settings = structuredClone(userSettings); // Set the current engine to "" so we can use the app default engine as // default settings.metaData.current = ""; // Update config by removing the app default engine await setConfigToLoad(CONFIG_V2_UPDATED); await loadEngines(settings); Assert.ok( stub.calledThrice, "_loadEngines should show the notification box." ); }); add_task(async function test_app_default_engine_change_start_up_still_exists() { stub.resetHistory(); let settings = structuredClone(userSettings); // Set the current engine to "" so we can use the app default engine as // default settings.metaData.current = ""; settings.metaData.appDefaultEngine = "engine_to_remove"; await setConfigToLoad(CONFIG_V2); await loadEngines(settings); Assert.ok( stub.notCalled, "_loadEngines should not show the notification box." ); }); async function setConfigToLoad(config) { SearchService.resetEngineSelector(); SearchTestUtils.setRemoteSettingsConfig(config); } function writeSettings(settings) { return IOUtils.writeJSON(settingsFilePath, settings, { compress: true }); } async function reloadEngines(settings) { let promiseSaved = promiseAfterSettings(); await SearchService._reloadEngines(settings); await promiseSaved; } async function loadEngines(settings) { await writeSettings(settings); let promiseSaved = promiseAfterSettings(); SearchService.reset(); await SearchService.init(); await promiseSaved; } async function assert_metadata_changed(settings) { info("Update region."); Region._setHomeRegion("FR", false); await reloadEngines(settings); Region._setHomeRegion("", false); let defaultEngineChanged = SearchTestUtils.promiseSearchNotification( SearchUtils.MODIFIED_TYPE.DEFAULT, SearchUtils.TOPIC_ENGINE_MODIFIED ); await reloadEngines(settings); Assert.ok( stub.notCalled, "_reloadEngines should not have shown the notification box." ); let newDefault = await defaultEngineChanged; Assert.equal( newDefault.name, "engine_to_remove", "Should have correctly notified the new default engine." ); Region._setHomeRegion("FR", false); await reloadEngines(settings); Region._setHomeRegion("", false); await loadEngines(settings); Assert.ok( stub.notCalled, "_loadEngines should not have shown the notification box." ); Assert.equal( SearchService.defaultEngine.name, "engine_to_remove", "Should have correctly notified the new default engine." ); }