91 lines
2.8 KiB
TypeScript
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();
|
|
});
|
|
});
|