interface MockEvent { claim: jest.Mock waitUntil?: jest.Mock } interface Listener { event: string cb: (event?: MockEvent) => void } describe("serviceWorker", () => { let listeners: Listener[] = [] let spy: jest.SpyInstance let claimSpy: jest.Mock let waitUntilSpy: jest.Mock function emit(event: string) { listeners .filter((listener) => listener.event === event) .forEach((listener) => { switch (event) { case "activate": listener.cb({ claim: jest.fn(), waitUntil: jest.fn(() => waitUntilSpy()), }) break default: listener.cb() } }) } beforeEach(() => { claimSpy = jest.fn() spy = jest.spyOn(console, "log") waitUntilSpy = jest.fn() Object.assign(global, { self: global, addEventListener: (event: string, cb: () => void) => { listeners.push({ event, cb }) }, clients: { claim: claimSpy.mockResolvedValue("claimed"), }, }) }) afterEach(() => { jest.restoreAllMocks() jest.resetModules() spy.mockClear() claimSpy.mockClear() // Clear all the listeners listeners = [] }) it("should add 3 listeners: install, activate and fetch", () => { require("../src/browser/serviceWorker.ts") const listenerEventNames = listeners.map((listener) => listener.event) expect(listeners).toHaveLength(3) expect(listenerEventNames).toContain("install") expect(listenerEventNames).toContain("activate") expect(listenerEventNames).toContain("fetch") }) it("should call the proper callbacks for 'install'", async () => { require("../src/browser/serviceWorker.ts") emit("install") expect(spy).toHaveBeenCalledWith("[Service Worker] installed") expect(spy).toHaveBeenCalledTimes(1) }) it("should do nothing when 'fetch' is called", async () => { require("../src/browser/serviceWorker.ts") emit("fetch") expect(spy).not.toHaveBeenCalled() }) it("should call the proper callbacks for 'activate'", async () => { require("../src/browser/serviceWorker.ts") emit("activate") // Activate serviceWorker expect(spy).toHaveBeenCalledWith("[Service Worker] activated") expect(waitUntilSpy).toHaveBeenCalled() expect(claimSpy).toHaveBeenCalled() }) })