import { render, waitFor } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import usePushNotifications from "../usePushNotifications";
// Hoisted so the vi.mock factories below can read it (Vitest hoists factories
// above module-scope consts).
const state = vi.hoisted(() => ({ isProduction: false }));
vi.mock("../../core/env", () => ({
ENV: {
get IS_PRODUCTION() {
return state.isProduction;
},
VAPID_PUBLIC_KEY: "",
},
}));
vi.mock("../../contexts", () => ({
useCurrentUserContext: () => ({
currentUser: { id: "user-1" },
hasRole: () => false,
}),
}));
vi.mock("../../features/push/data/push.service", () => ({
PushService: { register: vi.fn() },
}));
vi.mock("../../roles", () => ({
getRoleId: () => ({ Administrator: "administrator" }),
}));
vi.mock("../../client/config", () => ({
getAppUrl: () => "http://app.test",
}));
function Probe() {
usePushNotifications();
return null;
}
describe("usePushNotifications worker URL", () => {
const register = vi.fn().mockResolvedValue({ pushManager: { getSubscription: vi.fn() } });
beforeEach(() => {
register.mockClear();
vi.stubGlobal("navigator", { serviceWorker: { register, ready: Promise.resolve() } });
vi.stubGlobal("PushManager", function PushManager() {});
// "denied" makes the hook return right after registering, so this spec
// proves only the URL choice and nothing about subscription handling.
vi.stubGlobal("Notification", { permission: "denied", requestPermission: vi.fn() });
sessionStorage.clear();
});
afterEach(() => {
vi.unstubAllGlobals();
});
it("registers the push-only dev worker outside production", async () => {
state.isProduction = false;
render();
await waitFor(() => expect(register).toHaveBeenCalledWith("http://app.test/sw-dev.js"));
});
it("registers the full worker in production", async () => {
state.isProduction = true;
render();
await waitFor(() => expect(register).toHaveBeenCalledWith("http://app.test/sw.js"));
});
});