import React from "react"; import { mount } from "enzyme"; import { Provider } from "react-redux"; import { INITIAL_STATE, reducers } from "common/Reducers.sys.mjs"; import { combineReducers, createStore } from "redux"; import { Weather } from "content-src/components/Weather/Weather"; import { actionTypes as at } from "common/Actions.mjs"; import { LinkMenu } from "content-src/components/LinkMenu/LinkMenu"; const PREF_SYS_SHOW_WEATHER = "system.showWeather"; const PREF_SYS_SHOW_WEATHER_OPT_IN = "system.showWeatherOptIn"; const PREF_OPT_IN_DISPLAYED = "weather.optInDisplayed"; const PREF_OPT_IN_ACCEPTED = "weather.optInAccepted"; const PREF_STATIC_WEATHER_DATA = "weather.staticData.enabled"; // keeps initialize = true and provides fake suggestion + location data // so the component skips . const weatherInit = { initialized: true, suggestions: [ { forecast: { url: "https://example.com" }, current_conditions: { temperature: { c: 22, f: 72 }, icon_id: 3, summary: "Sunny", }, }, ], locationData: { city: "Testville" }, }; // base mockState for general Weather-rendering tests. // Opt-in is disabled here since it's only shown in specific locations const mockState = { ...INITIAL_STATE, Prefs: { ...INITIAL_STATE.Prefs, values: { ...INITIAL_STATE.Prefs.values, [PREF_SYS_SHOW_WEATHER]: true, [PREF_SYS_SHOW_WEATHER_OPT_IN]: false, }, }, Weather: { ...weatherInit }, }; // mock state for opt-in prompt tests. // Ensures the opt-in dialog appears by default. const optInMockState = { ...mockState, Prefs: { ...mockState.Prefs, values: { ...mockState.Prefs.values, showWeather: true, [PREF_SYS_SHOW_WEATHER_OPT_IN]: true, [PREF_OPT_IN_DISPLAYED]: true, [PREF_OPT_IN_ACCEPTED]: false, [PREF_STATIC_WEATHER_DATA]: true, "weather.locationSearchEnabled": true, "weather.display": "simple", "weather.temperatureUnits": "c", }, }, }; function WrapWithProvider({ children, state = INITIAL_STATE }) { const store = createStore(combineReducers(reducers), state); return {children}; } describe("", () => { let wrapper; let sandbox; let dispatch; beforeEach(() => { sandbox = sinon.createSandbox(); dispatch = sandbox.stub(); }); afterEach(() => { sandbox.restore(); wrapper?.unmount(); }); it("should render and show if the `system.showWeather` pref is enabled", () => { wrapper = mount( ); assert.ok(wrapper.exists()); assert.ok(wrapper.find(".weather").exists()); }); describe("Opt-in prompt actions", () => { it("should dispatch correct actions when user accepts weather opt-in", () => { const store = createStore(combineReducers(reducers), optInMockState); sinon.spy(store, "dispatch"); wrapper = mount( ); const acceptBtn = wrapper.find("#accept-opt-in"); acceptBtn.simulate("click", { preventDefault() {} }); const dispatchedActions = store.dispatch .getCalls() .map(call => call.args[0]); assert.ok( dispatchedActions.some( action => action.type === at.WEATHER_USER_OPT_IN_LOCATION ), "Expected WEATHER_USER_OPT_IN_LOCATION to be dispatched" ); assert.ok( dispatchedActions.some( action => action.type === at.WEATHER_OPT_IN_PROMPT_SELECTION && action.data === "accepted opt-in" ), "Expected WEATHER_OPT_IN_PROMPT_SELECTION with accepted opt-in" ); }); it("should render a shorter context menu when system.showWeatherOptIn is enabled", () => { wrapper = mount( ); // find the inner _Weather component (the real class) const inner = wrapper.find("_Weather"); assert.ok(inner.exists(), "Inner _Weather component should exist"); // toggle context menu state on the real instance inner.instance().setState({ showContextMenu: true }); wrapper.update(); const menu = wrapper.find(LinkMenu); assert.ok( menu.exists(), "Expected LinkMenu to render when context menu opened" ); const contextMenuOptions = menu.prop("options"); assert.deepEqual(contextMenuOptions, [ "ChangeWeatherLocation", "DetectLocation", "HideWeather", "OpenLearnMoreURL", ]); }); // TODO: Add test for "detect my location" telemetry once telemetry for that action is set up in another patch }); });