mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-09 08:42:15 +03:00
Compare commits
1 Commits
maint/cher
...
maint/cher
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b83853d55f |
@@ -8,8 +8,26 @@ export function PwaRegister() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable service worker in development to avoid chunk loading / HMR conflicts
|
||||
// Disable service worker in development to avoid chunk loading / HMR conflicts.
|
||||
// A visitor who previously loaded a production build on this origin (or an
|
||||
// older dev build from before this gate existed) can still have one left
|
||||
// over — it keeps intercepting navigations/assets, occasionally serving a
|
||||
// JS chunk that doesn't match the currently running dev server, which
|
||||
// triggers Next's dev-client auto-reload-on-chunk-mismatch recovery. Since
|
||||
// the stale worker never goes away on its own, that repeats forever
|
||||
// (visible as an unexplained refresh loop). Proactively unregister and
|
||||
// drop its caches instead of merely skipping a new registration.
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
navigator.serviceWorker
|
||||
.getRegistrations()
|
||||
.then((registrations) => Promise.all(registrations.map((r) => r.unregister())))
|
||||
.catch(() => {});
|
||||
if (typeof caches !== "undefined") {
|
||||
caches
|
||||
.keys()
|
||||
.then((keys) => Promise.all(keys.map((key) => caches.delete(key))))
|
||||
.catch(() => {});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
104
tests/unit/PwaRegister.test.tsx
Normal file
104
tests/unit/PwaRegister.test.tsx
Normal file
@@ -0,0 +1,104 @@
|
||||
// @vitest-environment jsdom
|
||||
import React from "react";
|
||||
import { act } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { PwaRegister } from "../../src/shared/components/PwaRegister";
|
||||
|
||||
const cleanupCallbacks: Array<() => void> = [];
|
||||
|
||||
function makeContainer(): HTMLElement {
|
||||
const container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
cleanupCallbacks.push(() => {
|
||||
container.remove();
|
||||
});
|
||||
return container;
|
||||
}
|
||||
|
||||
function mount() {
|
||||
const container = makeContainer();
|
||||
const root = createRoot(container);
|
||||
act(() => {
|
||||
root.render(<PwaRegister />);
|
||||
});
|
||||
cleanupCallbacks.push(() => root.unmount());
|
||||
}
|
||||
|
||||
describe("PwaRegister", () => {
|
||||
const originalServiceWorker = (navigator as any).serviceWorker;
|
||||
const originalCaches = (globalThis as any).caches;
|
||||
|
||||
afterEach(() => {
|
||||
cleanupCallbacks.splice(0).forEach((fn) => fn());
|
||||
vi.unstubAllGlobals();
|
||||
vi.unstubAllEnvs();
|
||||
Object.defineProperty(navigator, "serviceWorker", {
|
||||
value: originalServiceWorker,
|
||||
configurable: true,
|
||||
});
|
||||
(globalThis as any).caches = originalCaches;
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cleanupCallbacks.length = 0;
|
||||
});
|
||||
|
||||
it("unregisters leftover service workers and clears caches outside production", async () => {
|
||||
vi.stubEnv("NODE_ENV", "development");
|
||||
|
||||
const unregister1 = vi.fn().mockResolvedValue(true);
|
||||
const unregister2 = vi.fn().mockResolvedValue(true);
|
||||
const getRegistrations = vi
|
||||
.fn()
|
||||
.mockResolvedValue([{ unregister: unregister1 }, { unregister: unregister2 }]);
|
||||
const register = vi.fn();
|
||||
Object.defineProperty(navigator, "serviceWorker", {
|
||||
value: { getRegistrations, register },
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
const cachesDelete = vi.fn().mockResolvedValue(true);
|
||||
const cachesKeys = vi.fn().mockResolvedValue(["omniroute-pwa-v1", "omniroute-pwa-v2"]);
|
||||
(globalThis as any).caches = { keys: cachesKeys, delete: cachesDelete };
|
||||
|
||||
mount();
|
||||
// Flush the promise chains kicked off inside the effect.
|
||||
await act(async () => {
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
expect(getRegistrations).toHaveBeenCalledTimes(1);
|
||||
expect(unregister1).toHaveBeenCalledTimes(1);
|
||||
expect(unregister2).toHaveBeenCalledTimes(1);
|
||||
expect(cachesKeys).toHaveBeenCalledTimes(1);
|
||||
expect(cachesDelete).toHaveBeenCalledWith("omniroute-pwa-v1");
|
||||
expect(cachesDelete).toHaveBeenCalledWith("omniroute-pwa-v2");
|
||||
expect(register).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("registers the service worker in production without unregistering anything", async () => {
|
||||
vi.stubEnv("NODE_ENV", "production");
|
||||
|
||||
const getRegistrations = vi.fn().mockResolvedValue([]);
|
||||
const register = vi.fn().mockResolvedValue({});
|
||||
Object.defineProperty(navigator, "serviceWorker", {
|
||||
value: { getRegistrations, register },
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
const cachesKeys = vi.fn().mockResolvedValue([]);
|
||||
(globalThis as any).caches = { keys: cachesKeys, delete: vi.fn() };
|
||||
|
||||
mount();
|
||||
await act(async () => {
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
expect(register).toHaveBeenCalledWith("/sw.js");
|
||||
expect(getRegistrations).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user