diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:34:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:34:42 +0000 |
commit | da4c7e7ed675c3bf405668739c3012d140856109 (patch) | |
tree | cdd868dba063fecba609a1d819de271f0d51b23e /toolkit/components/search/tests/xpcshell/test_appProvided_icons_updates.js | |
parent | Adding upstream version 125.0.3. (diff) | |
download | firefox-da4c7e7ed675c3bf405668739c3012d140856109.tar.xz firefox-da4c7e7ed675c3bf405668739c3012d140856109.zip |
Adding upstream version 126.0.upstream/126.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/search/tests/xpcshell/test_appProvided_icons_updates.js')
-rw-r--r-- | toolkit/components/search/tests/xpcshell/test_appProvided_icons_updates.js | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/toolkit/components/search/tests/xpcshell/test_appProvided_icons_updates.js b/toolkit/components/search/tests/xpcshell/test_appProvided_icons_updates.js new file mode 100644 index 0000000000..4159b9f0fb --- /dev/null +++ b/toolkit/components/search/tests/xpcshell/test_appProvided_icons_updates.js @@ -0,0 +1,324 @@ +/* Any copyright is dedicated to the Public Domain. +https://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests to ensure that icons for application provided engines are correctly + * updated from remote settings. + */ + +"use strict"; + +// A skeleton configuration that gets filled in from TESTS during `add_setup`. +let CONFIG = [ + { + identifier: "engine_no_initial_icon", + recordType: "engine", + base: { + name: "engine_no_initial_icon name", + urls: { + search: { + base: "https://example.com/1", + searchTermParamName: "q", + }, + }, + }, + variants: [{ environment: { allRegionsAndLocales: true } }], + }, + { + identifier: "engine_icon_updates", + recordType: "engine", + base: { + name: "engine_icon_updates name", + urls: { + search: { + base: "https://example.com/2", + searchTermParamName: "q", + }, + }, + }, + variants: [{ environment: { allRegionsAndLocales: true } }], + }, + { + identifier: "engine_icon_not_local", + recordType: "engine", + base: { + name: "engine_icon_not_local name", + urls: { + search: { + base: "https://example.com/3", + searchTermParamName: "q", + }, + }, + }, + variants: [{ environment: { allRegionsAndLocales: true } }], + }, + { + identifier: "engine_icon_out_of_date", + recordType: "engine", + base: { + name: "engine_icon_out_of_date name", + urls: { + search: { + base: "https://example.com/4", + searchTermParamName: "q", + }, + }, + }, + variants: [{ environment: { allRegionsAndLocales: true } }], + }, + { + recordType: "defaultEngines", + globalDefault: "engine_no_initial_icon", + specificDefaults: [], + }, + { + recordType: "engineOrders", + orders: [], + }, +]; + +async function assertIconMatches(actualIconData, expectedIcon) { + let expectedBuffer = new Uint8Array(await getFileDataBuffer(expectedIcon)); + + Assert.equal( + actualIconData.length, + expectedBuffer.length, + "Should have received matching buffer lengths for the expected icon" + ); + Assert.ok( + actualIconData.every((value, index) => value === expectedBuffer[index]), + "Should have received matching data for the expected icon" + ); +} + +async function assertEngineIcon(engineName, expectedIcon) { + let engine = Services.search.getEngineByName(engineName); + let engineIconURL = await engine.getIconURL(16); + + if (expectedIcon) { + Assert.notEqual( + engineIconURL, + null, + "Should have an icon URL for the engine." + ); + + let response = await fetch(engineIconURL); + let buffer = new Uint8Array(await response.arrayBuffer()); + + await assertIconMatches(buffer, expectedIcon); + } else { + Assert.equal( + engineIconURL, + null, + "Should not have an icon URL for the engine." + ); + } +} + +let originalIconId = Services.uuid.generateUUID().toString(); +let client; + +add_setup(async function setup() { + useHttpServer(); + SearchTestUtils.useMockIdleService(); + + client = RemoteSettings("search-config-icons"); + await client.db.clear(); + + sinon.stub(client.attachments, "_baseAttachmentsURL").returns(gDataUrl); + + // Add some initial records and attachments into the remote settings collection. + await insertRecordIntoCollection(client, { + id: originalIconId, + filename: "remoteIcon.ico", + // This uses a wildcard match to test the icon is still applied correctly. + engineIdentifiers: ["engine_icon_upd*"], + imageSize: 16, + }); + // This attachment is not cached, so we don't have it locally. + await insertRecordIntoCollection( + client, + { + id: Services.uuid.generateUUID().toString(), + filename: "bigIcon.ico", + engineIdentifiers: [ + // This also tests multiple engine idenifiers works. + "enterprise", + "next_generation", + "engine_icon_not_local", + ], + imageSize: 16, + }, + false + ); + + // Add a record that is out of date, and update it with a newer one, but don't + // cache the attachment for the new one. + let outOfDateRecordId = Services.uuid.generateUUID().toString(); + await insertRecordIntoCollection( + client, + { + id: outOfDateRecordId, + filename: "remoteIcon.ico", + engineIdentifiers: ["engine_icon_out_of_date"], + imageSize: 16, + // 10 minutes ago. + lastModified: Date.now() - 600000, + }, + true + ); + let { record } = await mockRecordWithAttachment({ + id: outOfDateRecordId, + filename: "bigIcon.ico", + engineIdentifiers: ["engine_icon_out_of_date"], + imageSize: 16, + }); + await client.db.update(record); + await client.db.importChanges({}, record.lastModified); + + await SearchTestUtils.useTestEngines("simple-engines", null, CONFIG); + await Services.search.init(); + + // Testing that an icon is not local generates a `Could not find {id}...` + // message. + consoleAllowList.push("Could not find"); +}); + +add_task(async function test_icon_added_unknown_engine() { + // If the engine is unknown, and this is a new icon, we should still download + // the icon, in case the engine is added to the configuration later. + let newIconId = Services.uuid.generateUUID().toString(); + + let mock = await mockRecordWithAttachment({ + id: newIconId, + filename: "bigIcon.ico", + engineIdentifiers: ["engine_unknown"], + imageSize: 16, + }); + await client.db.update(mock.record, Date.now()); + + await client.emit("sync", { + data: { + current: [mock.record], + created: [mock.record], + updated: [], + deleted: [], + }, + }); + + SearchTestUtils.idleService._fireObservers("idle"); + + let icon; + await TestUtils.waitForCondition(async () => { + try { + icon = await client.attachments.get(mock.record); + } catch (ex) { + // Do nothing. + } + return !!icon; + }, "Should have loaded the icon into the attachments store."); + + await assertIconMatches(new Uint8Array(icon.buffer), "bigIcon.ico"); +}); + +add_task(async function test_icon_added_existing_engine() { + // If the engine is unknown, and this is a new icon, we should still download + // it, in case the engine is added to the configuration later. + let newIconId = Services.uuid.generateUUID().toString(); + + let mock = await mockRecordWithAttachment({ + id: newIconId, + filename: "bigIcon.ico", + engineIdentifiers: ["engine_no_initial_icon"], + imageSize: 16, + }); + await client.db.update(mock.record, Date.now()); + + let promiseEngineUpdated = SearchTestUtils.promiseSearchNotification( + SearchUtils.MODIFIED_TYPE.CHANGED, + SearchUtils.TOPIC_ENGINE_MODIFIED + ); + + await client.emit("sync", { + data: { + current: [mock.record], + created: [mock.record], + updated: [], + deleted: [], + }, + }); + + SearchTestUtils.idleService._fireObservers("idle"); + + await promiseEngineUpdated; + await assertEngineIcon("engine_no_initial_icon name", "bigIcon.ico"); +}); + +add_task(async function test_icon_updated() { + // Test that when an update for an engine icon is received, the engine is + // correctly updated. + + // Check the engine has the expected icon to start with. + await assertEngineIcon("engine_icon_updates name", "remoteIcon.ico"); + + // Update the icon for the engine. + let mock = await mockRecordWithAttachment({ + id: originalIconId, + filename: "bigIcon.ico", + engineIdentifiers: ["engine_icon_upd*"], + imageSize: 16, + }); + await client.db.update(mock.record, Date.now()); + + let promiseEngineUpdated = SearchTestUtils.promiseSearchNotification( + SearchUtils.MODIFIED_TYPE.CHANGED, + SearchUtils.TOPIC_ENGINE_MODIFIED + ); + + await client.emit("sync", { + data: { + current: [mock.record], + created: [], + updated: [{ new: mock.record }], + deleted: [], + }, + }); + SearchTestUtils.idleService._fireObservers("idle"); + + await promiseEngineUpdated; + await assertEngineIcon("engine_icon_updates name", "bigIcon.ico"); +}); + +add_task(async function test_icon_not_local() { + // Tests that a download is queued and triggered when the icon for an engine + // is not in either the local dump nor the cache. + + await assertEngineIcon("engine_icon_not_local name", null); + + // A download should have been queued, so fire idle to trigger it. + let promiseEngineUpdated = SearchTestUtils.promiseSearchNotification( + SearchUtils.MODIFIED_TYPE.CHANGED, + SearchUtils.TOPIC_ENGINE_MODIFIED + ); + SearchTestUtils.idleService._fireObservers("idle"); + await promiseEngineUpdated; + + await assertEngineIcon("engine_icon_not_local name", "bigIcon.ico"); +}); + +add_task(async function test_icon_out_of_date() { + // Tests that a download is queued and triggered when the icon for an engine + // is not in either the local dump nor the cache. + + await assertEngineIcon("engine_icon_out_of_date name", "remoteIcon.ico"); + + // A download should have been queued, so fire idle to trigger it. + let promiseEngineUpdated = SearchTestUtils.promiseSearchNotification( + SearchUtils.MODIFIED_TYPE.CHANGED, + SearchUtils.TOPIC_ENGINE_MODIFIED + ); + SearchTestUtils.idleService._fireObservers("idle"); + await promiseEngineUpdated; + + await assertEngineIcon("engine_icon_out_of_date name", "bigIcon.ico"); +}); |