diff --git a/frontend/__tests__/entry_test.tsx b/frontend/__tests__/entry_test.tsx index 3b06bc3c6..9067cdc34 100644 --- a/frontend/__tests__/entry_test.tsx +++ b/frontend/__tests__/entry_test.tsx @@ -17,13 +17,10 @@ import I from "i18next"; describe("entry file", () => { it("Calls the expected callbacks", async () => { - console.log = jest.fn(); - await import("../entry"); expect(stopIE).toHaveBeenCalled(); expect(detectLanguage).toHaveBeenCalled(); expect(I.init).toHaveBeenCalled(); - expect(console.log).toHaveBeenCalledWith("ABCD"); }); }); diff --git a/frontend/connectivity/__tests__/index_test.ts b/frontend/connectivity/__tests__/index_test.ts index d77e3aa4c..640a28845 100644 --- a/frontend/connectivity/__tests__/index_test.ts +++ b/frontend/connectivity/__tests__/index_test.ts @@ -1,17 +1,44 @@ -const mockRedux = { store: { dispatch: jest.fn() } }; -jest.mock("../../redux/store", () => mockRedux); +jest.mock("../../redux/store", () => { + return { + store: { + dispatch: jest.fn(), + getState: jest.fn((): DeepPartial => ({ + bot: { + connectivity: { + pings: { + "already_complete": { + kind: "complete", + start: 1, + end: 2 + } + } + } + } + })) + } + }; +}); jest.mock("../auto_sync_handle_inbound", () => ({ handleInbound: jest.fn() })); -import { dispatchNetworkUp, dispatchNetworkDown } from "../index"; +import { dispatchNetworkUp, dispatchNetworkDown, dispatchQosStart, networkUptimeThrottleStats } from "../index"; import { networkUp, networkDown } from "../actions"; import { GetState } from "../../redux/interfaces"; import { autoSync, routeMqttData } from "../auto_sync"; import { handleInbound } from "../auto_sync_handle_inbound"; +import { store } from "../../redux/store"; +import { DeepPartial } from "redux"; +import { Everything } from "../../interfaces"; +import { now } from "../../devices/connectivity/qos"; const NOW = new Date(); const SHORT_TIME_LATER = new Date(NOW.getTime() + 500).getTime(); const LONGER_TIME_LATER = new Date(NOW.getTime() + 5000).getTime(); +const resetStats = () => { + networkUptimeThrottleStats["user.api"] = 0; + networkUptimeThrottleStats["user.mqtt"] = 0; + networkUptimeThrottleStats["bot.mqtt"] = 0; +}; describe("dispatchNetworkUp", () => { const NOW_UP = networkUp("bot.mqtt", NOW.getTime()); @@ -19,25 +46,36 @@ describe("dispatchNetworkUp", () => { it("calls redux directly", () => { dispatchNetworkUp("bot.mqtt", NOW.getTime()); - expect(mockRedux.store.dispatch).toHaveBeenLastCalledWith(NOW_UP); + expect(store.dispatch).toHaveBeenLastCalledWith(NOW_UP); dispatchNetworkUp("bot.mqtt", SHORT_TIME_LATER); - expect(mockRedux.store.dispatch).toHaveBeenLastCalledWith(NOW_UP); + expect(store.dispatch).toHaveBeenLastCalledWith(NOW_UP); dispatchNetworkUp("bot.mqtt", LONGER_TIME_LATER); - expect(mockRedux.store.dispatch).toHaveBeenLastCalledWith(LATER_UP); + expect(store.dispatch).toHaveBeenLastCalledWith(LATER_UP); }); }); describe("dispatchNetworkDown", () => { const NOW_DOWN = networkDown("user.api", NOW.getTime()); const LATER_DOWN = networkDown("user.api", LONGER_TIME_LATER); + beforeEach(resetStats); it("calls redux directly", () => { dispatchNetworkDown("user.api", NOW.getTime()); - expect(mockRedux.store.dispatch).toHaveBeenLastCalledWith(NOW_DOWN); + expect(store.dispatch).toHaveBeenLastCalledWith(NOW_DOWN); dispatchNetworkDown("user.api", SHORT_TIME_LATER); - expect(mockRedux.store.dispatch).toHaveBeenLastCalledWith(NOW_DOWN); + expect(store.dispatch).toHaveBeenLastCalledWith(NOW_DOWN); dispatchNetworkDown("user.api", LONGER_TIME_LATER); - expect(mockRedux.store.dispatch).toHaveBeenLastCalledWith(LATER_DOWN); + expect(store.dispatch).toHaveBeenLastCalledWith(LATER_DOWN); + }); + + it("does not falsely mark network of being down", () => { + // This test uses mocked state. + // Please see `jest.mock` calls above. + dispatchNetworkDown("bot.mqtt", now(), "already_complete"); + expect(store.dispatch).not.toHaveBeenCalled(); + resetStats(); + dispatchNetworkDown("bot.mqtt", now(), "not_complete"); + expect(store.dispatch).toHaveBeenCalled(); }); }); @@ -52,3 +90,12 @@ describe("autoSync", () => { expect(handleInbound).toHaveBeenCalledWith(dispatch, getState, rmd); }); }); + +describe("dispatchQosStart", () => { + it("dispatches when a QoS ping is starting", () => { + const id = "hello"; + dispatchQosStart(id); + expect(store.dispatch) + .toHaveBeenCalledWith({ type: "START_QOS_PING", payload: { id } }); + }); +}); diff --git a/frontend/connectivity/index.ts b/frontend/connectivity/index.ts index 19a6b129c..13e279760 100644 --- a/frontend/connectivity/index.ts +++ b/frontend/connectivity/index.ts @@ -11,18 +11,20 @@ unavoidable. */ /** throttle calls to these functions to avoid unnecessary re-paints. */ const SLOWDOWN_TIME = 1500; -const lastCalledAt: Record = { - "user.api": 0, "user.mqtt": 0, "bot.mqtt": 0 +export const networkUptimeThrottleStats: Record = { + "user.api": 0, + "user.mqtt": 0, + "bot.mqtt": 0 }; function shouldThrottle(edge: Edge, now: number): boolean { - const then = lastCalledAt[edge]; + const then = networkUptimeThrottleStats[edge]; const diff = now - then; return diff < SLOWDOWN_TIME; } function bumpThrottle(edge: Edge, now: number) { - lastCalledAt[edge] = now; + networkUptimeThrottleStats[edge] = now; } export const dispatchQosStart = (id: string) => { @@ -56,7 +58,7 @@ export let dispatchNetworkDown = (edge: Edge, at: number, qosPingId?: string) => // so we need to add a means of cancelling the // "network down" action if the request completed // before the timeout. - if (qosPingId && pingAlreadyComplete(qosPingId)) { return; } + if (pingAlreadyComplete(qosPingId)) { return; } store.dispatch(networkDown(edge, at, qosPingId)); bumpThrottle(edge, at); };