diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
commit | d8bbc7858622b6d9c278469aab701ca0b609cddf (patch) | |
tree | eff41dc61d9f714852212739e6b3738b82a2af87 /toolkit/components/contentrelevancy/tests | |
parent | Releasing progress-linux version 125.0.3-1~progress7.99u1. (diff) | |
download | firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip |
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/contentrelevancy/tests')
6 files changed, 359 insertions, 0 deletions
diff --git a/toolkit/components/contentrelevancy/tests/browser/browser.toml b/toolkit/components/contentrelevancy/tests/browser/browser.toml new file mode 100644 index 0000000000..ec1d3a3e66 --- /dev/null +++ b/toolkit/components/contentrelevancy/tests/browser/browser.toml @@ -0,0 +1,6 @@ +[DEFAULT] +prefs = [ + "toolkit.contentRelevancy.enabled=false", +] + +["browser_contentrelevancy_nimbus.js"] diff --git a/toolkit/components/contentrelevancy/tests/browser/browser_contentrelevancy_nimbus.js b/toolkit/components/contentrelevancy/tests/browser/browser_contentrelevancy_nimbus.js new file mode 100644 index 0000000000..47d54c2a87 --- /dev/null +++ b/toolkit/components/contentrelevancy/tests/browser/browser_contentrelevancy_nimbus.js @@ -0,0 +1,91 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { ExperimentAPI } = ChromeUtils.importESModule( + "resource://nimbus/ExperimentAPI.sys.mjs" +); +const { ExperimentFakes } = ChromeUtils.importESModule( + "resource://testing-common/NimbusTestUtils.sys.mjs" +); +const { ContentRelevancyManager } = ChromeUtils.importESModule( + "resource://gre/modules/ContentRelevancyManager.sys.mjs" +); +const { sinon } = ChromeUtils.importESModule( + "resource://testing-common/Sinon.sys.mjs" +); + +let gSandbox; + +add_setup(() => { + gSandbox = sinon.createSandbox(); + + registerCleanupFunction(() => { + gSandbox.restore(); + }); +}); + +/** + * Test Nimbus integration - enable. + */ +add_task(async function test_NimbusIntegration_enable() { + gSandbox.spy(ContentRelevancyManager, "notify"); + + await ExperimentAPI.ready(); + const doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({ + featureId: "contentRelevancy", + value: { + enabled: true, + minInputUrls: 1, + maxInputUrls: 3, + // Set the timer interval to 0 will trigger the timer right away. + timerInterval: 0, + }, + }); + + await TestUtils.waitForCondition( + () => ContentRelevancyManager.shouldEnable, + "Should enable it via Nimbus" + ); + + await TestUtils.waitForCondition( + () => ContentRelevancyManager.notify.called, + "The timer callback should be called" + ); + + await doExperimentCleanup(); + gSandbox.restore(); +}); + +/** + * Test Nimbus integration - disable. + */ +add_task(async function test_NimbusIntegration_disable() { + gSandbox.spy(ContentRelevancyManager, "notify"); + + await ExperimentAPI.ready(); + const doExperimentCleanup = await ExperimentFakes.enrollWithFeatureConfig({ + featureId: "contentRelevancy", + value: { + enabled: false, + minInputUrls: 1, + maxInputUrls: 3, + // Set the timer interval to 0 will trigger the timer right away. + timerInterval: 0, + }, + }); + + await TestUtils.waitForCondition( + () => !ContentRelevancyManager.shouldEnable, + "Should disable it via Nimbus" + ); + + await TestUtils.waitForCondition( + () => ContentRelevancyManager.notify.notCalled, + "The timer callback should not be called" + ); + + await doExperimentCleanup(); + gSandbox.restore(); +}); diff --git a/toolkit/components/contentrelevancy/tests/xpcshell/head.js b/toolkit/components/contentrelevancy/tests/xpcshell/head.js new file mode 100644 index 0000000000..e8c31f589c --- /dev/null +++ b/toolkit/components/contentrelevancy/tests/xpcshell/head.js @@ -0,0 +1,6 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// This requires the profile directory for Places and the content relevancy +// component needs a profile directory for storage. +do_get_profile(); diff --git a/toolkit/components/contentrelevancy/tests/xpcshell/test_ContentRelevancyManager.js b/toolkit/components/contentrelevancy/tests/xpcshell/test_ContentRelevancyManager.js new file mode 100644 index 0000000000..633f9fc49b --- /dev/null +++ b/toolkit/components/contentrelevancy/tests/xpcshell/test_ContentRelevancyManager.js @@ -0,0 +1,149 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +ChromeUtils.defineESModuleGetters(this, { + ContentRelevancyManager: + "resource://gre/modules/ContentRelevancyManager.sys.mjs", + TestUtils: "resource://testing-common/TestUtils.sys.mjs", + setTimeout: "resource://gre/modules/Timer.sys.mjs", + sinon: "resource://testing-common/Sinon.sys.mjs", +}); + +const PREF_CONTENT_RELEVANCY_ENABLED = "toolkit.contentRelevancy.enabled"; +const PREF_TIMER_INTERVAL = "toolkit.contentRelevancy.timerInterval"; + +// These consts are copied from the update timer manager test. See +// `initUpdateTimerManager()`. +const PREF_APP_UPDATE_TIMERMINIMUMDELAY = "app.update.timerMinimumDelay"; +const PREF_APP_UPDATE_TIMERFIRSTINTERVAL = "app.update.timerFirstInterval"; +const MAIN_TIMER_INTERVAL = 1000; // milliseconds +const CATEGORY_UPDATE_TIMER = "update-timer"; + +let gSandbox; + +add_setup(async () => { + gSandbox = sinon.createSandbox(); + initUpdateTimerManager(); + Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, true); + await ContentRelevancyManager.init(); + + registerCleanupFunction(() => { + Services.prefs.clearUserPref(PREF_CONTENT_RELEVANCY_ENABLED); + gSandbox.restore(); + }); +}); + +add_task(async function test_init() { + Assert.ok(ContentRelevancyManager.initialized, "Init should succeed"); +}); + +add_task(async function test_uninit() { + ContentRelevancyManager.uninit(); + + Assert.ok(!ContentRelevancyManager.initialized, "Uninit should succeed"); +}); + +add_task(async function test_timer() { + // Set the timer interval to 0 will trigger the timer right away. + Services.prefs.setIntPref(PREF_TIMER_INTERVAL, 0); + gSandbox.spy(ContentRelevancyManager, "notify"); + + await ContentRelevancyManager.init(); + + await TestUtils.waitForCondition( + () => ContentRelevancyManager.notify.called, + "The timer callback should be called" + ); + + Services.prefs.clearUserPref(PREF_TIMER_INTERVAL); + gSandbox.restore(); +}); + +add_task(async function test_feature_toggling() { + Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, false); + // Set the timer interval to 0 will trigger the timer right away. + Services.prefs.setIntPref(PREF_TIMER_INTERVAL, 0); + gSandbox.spy(ContentRelevancyManager, "notify"); + + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + await new Promise(resolve => setTimeout(resolve, 1100)); + Assert.ok( + ContentRelevancyManager.notify.notCalled, + "Timer should not be registered if disabled" + ); + + // Toggle the pref again should re-enable the feature. + Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, true); + await TestUtils.waitForTick(); + + await TestUtils.waitForCondition( + () => ContentRelevancyManager.notify.called, + "The timer callback should be called" + ); + + Services.prefs.clearUserPref(PREF_CONTENT_RELEVANCY_ENABLED); + Services.prefs.clearUserPref(PREF_TIMER_INTERVAL); + gSandbox.restore(); +}); + +add_task(async function test_call_disable_twice() { + Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, false); + await TestUtils.waitForTick(); + + Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, false); + await TestUtils.waitForTick(); + + Assert.ok(true, "`#disable` should be safe to call multiple times"); + + Services.prefs.clearUserPref(PREF_CONTENT_RELEVANCY_ENABLED); +}); + +add_task(async function test_doClassification() { + Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, true); + await TestUtils.waitForCondition(() => ContentRelevancyManager._isStoreReady); + await ContentRelevancyManager._test_doClassification([]); + + // Disable it to reset the store. + Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, false); + await TestUtils.waitForTick(); + + await Assert.rejects( + ContentRelevancyManager._test_doClassification([]), + /Store is not available/, + "Should throw with an unset store" + ); + + Services.prefs.clearUserPref(PREF_CONTENT_RELEVANCY_ENABLED); +}); + +/** + * Sets up the update timer manager for testing: makes it fire more often, + * removes all existing timers, and initializes it for testing. The body of this + * function is copied from: + * https://searchfox.org/mozilla-central/source/toolkit/components/timermanager/tests/unit/consumerNotifications.js + */ +function initUpdateTimerManager() { + // Set the timer to fire every second + Services.prefs.setIntPref( + PREF_APP_UPDATE_TIMERMINIMUMDELAY, + MAIN_TIMER_INTERVAL / 1000 + ); + Services.prefs.setIntPref( + PREF_APP_UPDATE_TIMERFIRSTINTERVAL, + MAIN_TIMER_INTERVAL + ); + + // Remove existing update timers to prevent them from being notified + for (let { data: entry } of Services.catMan.enumerateCategory( + CATEGORY_UPDATE_TIMER + )) { + Services.catMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, entry, false); + } + + Cc["@mozilla.org/updates/timer-manager;1"] + .getService(Ci.nsIUpdateTimerManager) + .QueryInterface(Ci.nsIObserver) + .observe(null, "utm-test-init", ""); +} diff --git a/toolkit/components/contentrelevancy/tests/xpcshell/test_InputUtils.js b/toolkit/components/contentrelevancy/tests/xpcshell/test_InputUtils.js new file mode 100644 index 0000000000..2bb2b8e62e --- /dev/null +++ b/toolkit/components/contentrelevancy/tests/xpcshell/test_InputUtils.js @@ -0,0 +1,98 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +ChromeUtils.defineESModuleGetters(this, { + getFrecentRecentCombinedUrls: + "resource://gre/modules/contentrelevancy/private/InputUtils.sys.mjs", + getMostRecentUrls: + "resource://gre/modules/contentrelevancy/private/InputUtils.sys.mjs", + getTopFrecentUrls: + "resource://gre/modules/contentrelevancy/private/InputUtils.sys.mjs", + PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs", + PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs", +}); + +const FRECENCY_SCORE_FOR_ONE_VISIT = 100; +const TEST_VISITS = [ + "http://test-1.com/", + "http://test-2.com/", + "http://test-3.com/", + "http://test-4.com/", +]; + +add_task(async function test_GetTopFrecentUrls() { + await PlacesUtils.history.clear(); + let urls = new Set(await getTopFrecentUrls(3, FRECENCY_SCORE_FOR_ONE_VISIT)); + + Assert.strictEqual(urls.size, 0, "Should have no top frecent links."); + + await PlacesTestUtils.addVisits(TEST_VISITS); + urls = new Set(await getTopFrecentUrls(3, FRECENCY_SCORE_FOR_ONE_VISIT)); + + Assert.strictEqual(urls.size, 3, "Should fetch the expected links"); + urls.forEach(url => { + Assert.ok(TEST_VISITS.includes(url), "Should be a link of the test visits"); + }); +}); + +add_task(async function test_GetMostRecentUrls() { + await PlacesUtils.history.clear(); + let urls = new Set(await getMostRecentUrls(3)); + + Assert.strictEqual(urls.size, 0, "Should have no recent links."); + + // Add visits and page meta data. + await PlacesTestUtils.addVisits(TEST_VISITS); + for (let url of TEST_VISITS) { + await PlacesUtils.history.update({ + description: "desc", + previewImageURL: "https://image/", + url, + }); + } + + urls = new Set(await getMostRecentUrls(3)); + + Assert.strictEqual(urls.size, 3, "Should fetch the expected links"); + urls.forEach(url => { + Assert.ok(TEST_VISITS.includes(url), "Should be a link of the test visits"); + }); +}); + +add_task(async function test_GetFrecentRecentCombinedUrls() { + await PlacesUtils.history.clear(); + let urls = new Set(await getFrecentRecentCombinedUrls(3)); + + Assert.strictEqual(urls.size, 0, "Should have no links."); + + // Add visits and page meta data. + await PlacesTestUtils.addVisits(TEST_VISITS); + for (let url of TEST_VISITS) { + await PlacesUtils.history.update({ + description: "desc", + previewImageURL: "https://image/", + url, + }); + } + + urls = new Set(await getFrecentRecentCombinedUrls(3)); + + Assert.strictEqual(urls.size, 3, "Should fetch the expected links"); + urls.forEach(url => { + Assert.ok(TEST_VISITS.includes(url), "Should be a link of the test visits"); + }); + + // Try getting twice as many URLs as the total in Places. + urls = new Set(await getFrecentRecentCombinedUrls(TEST_VISITS.length * 2)); + + Assert.strictEqual( + urls.size, + TEST_VISITS.length, + "Should not include duplicates" + ); + urls.forEach(url => { + Assert.ok(TEST_VISITS.includes(url), "Should be a link of the test visits"); + }); +}); diff --git a/toolkit/components/contentrelevancy/tests/xpcshell/xpcshell.toml b/toolkit/components/contentrelevancy/tests/xpcshell/xpcshell.toml new file mode 100644 index 0000000000..70f6d45c2d --- /dev/null +++ b/toolkit/components/contentrelevancy/tests/xpcshell/xpcshell.toml @@ -0,0 +1,9 @@ +[DEFAULT] +head = "head.js" +firefox-appdir = "browser" + +["test_ContentRelevancyManager.js"] +skip-if = ["os == 'android'"] # bug 1886601 + +["test_InputUtils.js"] +skip-if = ["os == 'android'"] # bug 1886601 |