commit 0e9a2537c7b5fe837efb624db3ed122f69063fe3
parent 79cf28a5d8e33529610c6b2e0aad985203c9334b
Author: Reem H <42309026+reemhamz@users.noreply.github.com>
Date: Thu, 2 Oct 2025 21:46:37 +0000
Bug 1991571 - Write feed tests for weather opt-in feature. r=home-newtab-reviewers,nbarrett
Differential Revision: https://phabricator.services.mozilla.com/D267164
Diffstat:
1 file changed, 177 insertions(+), 0 deletions(-)
diff --git a/browser/extensions/newtab/test/xpcshell/test_WeatherFeed.js b/browser/extensions/newtab/test/xpcshell/test_WeatherFeed.js
@@ -9,6 +9,7 @@ ChromeUtils.defineESModuleGetters(this, {
sinon: "resource://testing-common/Sinon.sys.mjs",
MerinoTestUtils: "resource://testing-common/MerinoTestUtils.sys.mjs",
WeatherFeed: "resource://newtab/lib/WeatherFeed.sys.mjs",
+ Region: "resource://gre/modules/Region.sys.mjs",
});
const { WEATHER_SUGGESTION } = MerinoTestUtils;
@@ -44,6 +45,64 @@ add_task(async function test_construction() {
sandbox.restore();
});
+add_task(async function test_checkOptInRegion() {
+ let sandbox = sinon.createSandbox();
+
+ sandbox.stub(WeatherFeed.prototype, "PersistentCache").returns({
+ set: () => {},
+ get: () => {},
+ });
+
+ let feed = new WeatherFeed();
+
+ feed.store = {
+ dispatch: sinon.spy(),
+ getState() {
+ return { Prefs: { values: {} } };
+ },
+ };
+
+ sandbox.stub(feed, "isEnabled").returns(true);
+
+ // First case: If home region is in the opt-in list, showWeatherOptIn should be true
+ // Region._setHomeRegion() is the supported way to control region in tests:
+ // https://firefox-source-docs.mozilla.org/toolkit/modules/toolkit_modules/Region.html#testing
+ // We used false here because that second argument is a change observer that will fire an event.
+ // So keeping it false silently sets the region for our test
+ Region._setHomeRegion("FR", false);
+ let resultTrue = await feed.checkOptInRegion();
+
+ Assert.strictEqual(
+ resultTrue,
+ true,
+ "Returns true for region in opt-in list"
+ );
+ Assert.ok(
+ feed.store.dispatch.calledWith(
+ actionCreators.SetPref("system.showWeatherOptIn", true)
+ ),
+ "Dispatch sets system.showWeatherOptIn to true when region is in opt-in list"
+ );
+
+ // Second case: If home region is not in the opt-in list, showWeatherOptIn should be false
+ Region._setHomeRegion("ZZ", false);
+ let resultFalse = await feed.checkOptInRegion();
+
+ Assert.strictEqual(
+ resultFalse,
+ false,
+ "Returns false for region not found in opt-in list"
+ );
+ Assert.ok(
+ feed.store.dispatch.calledWith(
+ actionCreators.SetPref("system.showWeatherOptIn", false)
+ ),
+ "Dispatch sets system.showWeatherOptIn to false when region is not in opt-in list"
+ );
+
+ sandbox.restore();
+});
+
add_task(async function test_onAction_INIT() {
let sandbox = sinon.createSandbox();
sandbox.stub(WeatherFeed.prototype, "MerinoClient").returns({
@@ -110,3 +169,121 @@ add_task(async function test_onAction_INIT() {
Services.prefs.clearUserPref(WEATHER_ENABLED);
sandbox.restore();
});
+
+// Test if location lookup was successful
+add_task(async function test_onAction_opt_in_location_success() {
+ let sandbox = sinon.createSandbox();
+
+ sandbox.stub(WeatherFeed.prototype, "PersistentCache").returns({
+ set: () => {},
+ get: () => {},
+ });
+
+ let feed = new WeatherFeed();
+
+ feed.store = {
+ dispatch: sinon.spy(),
+ getState() {
+ return { Prefs: { values: {} } };
+ },
+ };
+
+ // Stub fetchLocationByIP() to simulate a successful lookup
+ sandbox.stub(feed, "fetchLocationByIP").resolves({
+ localized_name: "Testville",
+ administrative_area: "Paris",
+ country: "FR",
+ key: "12345",
+ });
+
+ await feed.onAction({ type: actionTypes.WEATHER_USER_OPT_IN_LOCATION });
+
+ Assert.ok(
+ feed.store.dispatch.calledWith(
+ actionCreators.SetPref("weather.optInAccepted", true)
+ )
+ );
+ Assert.ok(
+ feed.store.dispatch.calledWith(
+ actionCreators.SetPref("weather.optInDisplayed", false)
+ )
+ );
+
+ // Assert location data broadcasted to content
+ Assert.ok(
+ feed.store.dispatch.calledWith(
+ actionCreators.BroadcastToContent({
+ type: actionTypes.WEATHER_LOCATION_DATA_UPDATE,
+ data: {
+ city: "Testville",
+ adminName: "Paris",
+ country: "FR",
+ },
+ })
+ ),
+ "Broadcasts WEATHER_LOCATION_DATA_UPDATE with normalized location data"
+ );
+
+ Assert.ok(
+ feed.store.dispatch.calledWith(
+ actionCreators.SetPref("weather.query", "12345")
+ ),
+ "Sets weather.query pref from location key"
+ );
+
+ sandbox.restore();
+});
+
+// Test if no location was found
+add_task(async function test_onAction_opt_in_no_location_found() {
+ let sandbox = sinon.createSandbox();
+
+ sandbox.stub(WeatherFeed.prototype, "PersistentCache").returns({
+ set: () => {},
+ get: () => {},
+ });
+
+ let feed = new WeatherFeed();
+
+ feed.store = {
+ dispatch: sinon.spy(),
+ getState() {
+ return { Prefs: { values: {} } };
+ },
+ };
+
+ // Test that fetchLocationByIP doesn't return a location
+ sandbox.stub(feed, "fetchLocationByIP").resolves(null);
+
+ await feed.onAction({ type: actionTypes.WEATHER_USER_OPT_IN_LOCATION });
+
+ // Ensure the pref flips always happens so user won’t see the opt-in again
+ Assert.ok(
+ feed.store.dispatch.calledWith(
+ actionCreators.SetPref("weather.optInAccepted", true)
+ )
+ );
+ Assert.ok(
+ feed.store.dispatch.calledWith(
+ actionCreators.SetPref("weather.optInDisplayed", false)
+ )
+ );
+
+ Assert.ok(
+ !feed.store.dispatch.calledWithMatch(
+ actionCreators.BroadcastToContent({
+ type: actionTypes.WEATHER_LOCATION_DATA_UPDATE,
+ })
+ ),
+ "Doesn't broadcast location data if location not found"
+ );
+
+ Assert.ok(
+ !feed.store.dispatch.calledWith(
+ actionCreators.SetPref("weather.query", sinon.match.any)
+ ),
+ "Does not set weather.query if no detected location"
+ );
+
+ sandbox.restore();
+});