import React from "react";
import { Text } from "react-native";
import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
import { subscriberFor } from "@applicaster/zapp-react-native-utils/reactHooks/useSubscriberFor";
jest.useFakeTimers({ legacyFakeTimers: true });
// `isOnline` (@applicaster/quick-brick-core/App/NetworkStatusProvider/utils)
// only treats connectionInfo as "ready" when it has NetInfoState-shaped
// isConnected/isInternetReachable/details fields, so the mock has to mirror
// that shape for online/offline to actually be distinguishable.
let mockConnectionStatus = false;
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/connection", () => {
return {
...jest.requireActual(
"@applicaster/zapp-react-native-utils/reactHooks/connection"
),
useConnectionInfo: jest.fn(() => ({
details: {},
isConnected: mockConnectionStatus,
isInternetReachable: mockConnectionStatus,
})),
};
});
jest.mock("@applicaster/zapp-react-native-redux", () => ({
...jest.requireActual("@applicaster/zapp-react-native-redux"),
usePlugins: () => [
{
name: "offline experience",
identifier: "offline-experience",
type: "general",
module: {
useOfflineExperienceConfiguration: () => ({
configurationFields: {},
localizations: {
offline_toast_message: "No internet connection",
online_toast_message: "You are back online",
},
}),
},
},
],
}));
jest.mock("react-native-safe-area-context", () => ({
...jest.requireActual("react-native-safe-area-context"),
useSafeAreaInsets: () => ({ top: 44 }),
}));
describe("OfflineHandler", () => {
const { OfflineHandler } = require("../");
beforeEach(() => {
mockConnectionStatus = false;
});
it("renders its children without wrapping them in a notification view", () => {
const { toJSON } = renderWithProviders(
child content
);
expect(toJSON()).toMatchSnapshot();
});
it("emits a showToast event on mount when the device starts offline", () => {
mockConnectionStatus = false;
const handleShowToast = jest.fn();
const unsubscribe = subscriberFor("showToast", handleShowToast);
renderWithProviders();
expect(handleShowToast).toHaveBeenCalledWith(
expect.objectContaining({
id: "offline-status",
message: "No internet connection",
timeout: 5000,
}),
// the shared event bus appends a dispose fn as the last handler arg
expect.any(Function)
);
unsubscribe();
});
it("does not emit a showToast event on mount when the device starts online", () => {
mockConnectionStatus = true;
const handleShowToast = jest.fn();
const unsubscribe = subscriberFor("showToast", handleShowToast);
renderWithProviders();
expect(handleShowToast).not.toHaveBeenCalled();
unsubscribe();
});
it("emits a showToast event when the device comes back online", () => {
mockConnectionStatus = false;
const handleShowToast = jest.fn();
const unsubscribe = subscriberFor("showToast", handleShowToast);
const { rerender } = renderWithProviders();
// ignore the offline toast emitted on mount; we only care about the
// offline -> online transition here
handleShowToast.mockClear();
mockConnectionStatus = true;
rerender();
expect(handleShowToast).toHaveBeenCalledWith(
expect.objectContaining({
id: "offline-status",
message: "You are back online",
timeout: 2000,
}),
// the shared event bus appends a dispose fn as the last handler arg
expect.any(Function)
);
unsubscribe();
});
});