Files
clean-architecture-frontend…/tests/unit/optional-runtime-host.test.ts
T
2026-08-01 19:39:59 +09:00

91 lines
2.8 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import { createOptionalRuntimeHost } from "../../src/bootstrap/optional-runtime-host.ts";
import type { ResolvedRuntimeCapabilities } from "../../src/contracts/runtime-capabilities.ts";
import type {
ServiceWorkerRuntimeHost,
ServiceWorkerStartOutcome,
} from "../../src/contracts/service-worker.ts";
const capabilities: ResolvedRuntimeCapabilities = Object.freeze({
realtime: Object.freeze([]),
webWorkers: Object.freeze([]),
serviceWorker: null,
serviceWorkerDisabledCleanup: false,
offlineCommands: null,
});
function deferred<Value>() {
let resolve!: (value: Value) => void;
const promise = new Promise<Value>((settle) => {
resolve = settle;
});
return { promise, resolve } as const;
}
describe("optional runtime host", () => {
it("keeps stop-before-start terminal without acquiring browser resources", async () => {
const serviceWorker: ServiceWorkerRuntimeHost = {
start: vi.fn(
async (): Promise<ServiceWorkerStartOutcome> => ({
kind: "ACTIVE",
buildId: "build-1",
}),
),
requestActivation: vi.fn(),
resetOwnedCaches: vi.fn(),
stop: vi.fn(async () => {}),
};
const addEventListener = vi.fn();
const runtime = createOptionalRuntimeHost({
capabilities,
routerBasePath: "/",
buildId: "build-1",
serviceWorkerHost: serviceWorker,
browserLifecycleHost: {
addEventListener,
removeEventListener: vi.fn(),
},
});
await runtime.stop();
await runtime.startAfterMount();
expect(runtime.browserLifecycle()).toBeNull();
expect(runtime.health().serviceWorker).toBe("DISABLED");
expect(addEventListener).not.toHaveBeenCalled();
expect(serviceWorker.start).not.toHaveBeenCalled();
expect(serviceWorker.stop).not.toHaveBeenCalled();
});
it("serializes stop behind an in-flight start and suppresses late health", async () => {
const start = deferred<ServiceWorkerStartOutcome>();
const serviceWorker: ServiceWorkerRuntimeHost = {
start: vi.fn(() => start.promise),
requestActivation: vi.fn(),
resetOwnedCaches: vi.fn(),
stop: vi.fn(async () => {}),
};
const runtime = createOptionalRuntimeHost({
capabilities,
routerBasePath: "/",
buildId: "build-1",
serviceWorkerHost: serviceWorker,
browserLifecycleHost: {
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
},
});
const starting = runtime.startAfterMount();
const stopping = runtime.stop();
start.resolve({ kind: "ACTIVE", buildId: "build-1" });
await Promise.all([starting, stopping]);
expect(serviceWorker.stop).toHaveBeenCalledTimes(1);
expect(runtime.health().serviceWorker).toBe("DISABLED");
expect(runtime.browserLifecycle()).toBeNull();
});
});