import { expect, test, vi } from "vitest" import { Runtime } from "#Source/environment/index.ts" interface BunLike { version: string } const withBunGlobal = (run: (bunGlobal: BunLike) => void): void => { // When the suite already runs inside Bun, the real global exists and Vitest // cannot safely redefine it. Only stub Bun for runtimes that do not provide it. const existingBun = (globalThis as typeof globalThis & { Bun?: BunLike | undefined }).Bun if (existingBun !== undefined) { run(existingBun) return } const bunGlobal = { version: "1.0.0" } vi.stubGlobal("Bun", bunGlobal) try { run(bunGlobal) } finally { vi.unstubAllGlobals() } } test("isRuntimeRegistered detects built-in and missing runtime", () => { expect(Runtime.isRuntimeRegistered("nodejs")).toBe(true) expect(Runtime.isRuntimeRegistered("custom-runtime")).toBe(false) }) test("registerRuntime stores custom runtime", () => { Runtime.registerRuntime({ runtime: "custom-register", detect: () => false, getGlobalContext: () => ({ ok: true }), use: (_use, otherwise) => otherwise(), }) expect(Runtime.isRuntimeRegistered("custom-register")).toBe(true) Runtime.unregisterRuntime("custom-register") }) test("unregisterRuntime removes custom runtime", () => { Runtime.registerRuntime({ runtime: "custom-remove", detect: () => false, getGlobalContext: () => ({ ok: true }), use: (_use, otherwise) => otherwise(), }) Runtime.unregisterRuntime("custom-remove") expect(Runtime.isRuntimeRegistered("custom-remove")).toBe(false) }) test("listRuntimes returns runtime keys", () => { const runtimes = Runtime.listRuntimes() expect(runtimes).toContain("nodejs") expect(runtimes).toContain("unknown") }) test("isBrowser detects browser context", () => { const browserWindow = { document: { title: "mock" } } vi.stubGlobal("window", browserWindow) vi.stubGlobal("self", browserWindow) expect(Runtime.isBrowser()).toBe(true) vi.unstubAllGlobals() }) test("getRuntimeContextBrowser returns browser globals", () => { const browserWindow = { document: { title: "mock" } } vi.stubGlobal("window", browserWindow) vi.stubGlobal("self", browserWindow) const context = Runtime.getRuntimeContextBrowser() expect(context.window).toBe(browserWindow) expect(context.self).toBe(browserWindow) vi.unstubAllGlobals() }) test("useBrowser executes matched handler", { skip: false }, () => { const browserWindow = { document: { title: "mock" } } vi.stubGlobal("window", browserWindow) vi.stubGlobal("self", browserWindow) const browserResult = Runtime.useBrowser( (context) => context.window.document.title, () => "fallback", ) expect(browserResult).toBe("mock") vi.unstubAllGlobals() }) test("isNodejs detects Node.js runtime", () => { expect(Runtime.isNodejs()).toBe(true) }) test("getRuntimeContextNodejs returns node globals", () => { const context = Runtime.getRuntimeContextNodejs() expect(context.global).toBe(globalThis) expect(context.globalThis).toBe(globalThis) }) test("useNodejs executes node handler", () => { const nodeResult = Runtime.useNodejs( (context) => context.globalThis === globalThis, () => false, ) expect(nodeResult).toBe(true) }) test("isDeno detects deno runtime", () => { vi.stubGlobal("Deno", { version: { deno: "2.0.0" } }) expect(Runtime.isDeno()).toBe(true) vi.unstubAllGlobals() }) test("getRuntimeContextDeno returns deno context", () => { vi.stubGlobal("Deno", { version: { deno: "2.0.0" } }) const context = Runtime.getRuntimeContextDeno() expect(context.global).toBe(globalThis) vi.unstubAllGlobals() }) test("useDeno executes deno handler", () => { vi.stubGlobal("Deno", { version: { deno: "2.0.0" } }) const denoResult = Runtime.useDeno( (context) => context.globalThis === globalThis, () => false, ) expect(denoResult).toBe(true) vi.unstubAllGlobals() }) test("isBun detects bun runtime", () => { withBunGlobal(() => { expect(Runtime.isBun()).toBe(true) }) }) test("getRuntimeContextBun returns bun context", () => { withBunGlobal((bunGlobal) => { const context = Runtime.getRuntimeContextBun() expect(context.Bun).toBe(bunGlobal) }) }) test("useBun executes bun handler", () => { withBunGlobal(() => { const bunResult = Runtime.useBun( (context) => typeof context.Bun.version, () => "fallback", ) expect(bunResult).toBe("string") }) }) test("isWebWorker detects web worker runtime", () => { class WorkerGlobalScopeMock { readonly internalType = "worker" } class ServiceWorkerGlobalScopeMock extends WorkerGlobalScopeMock { readonly internalTypeService = "service-worker" } vi.stubGlobal("WorkerGlobalScope", WorkerGlobalScopeMock) vi.stubGlobal("ServiceWorkerGlobalScope", ServiceWorkerGlobalScopeMock) vi.stubGlobal("self", new WorkerGlobalScopeMock()) vi.stubGlobal("process", undefined) vi.stubGlobal("window", undefined) expect(Runtime.isWebWorker()).toBe(true) vi.unstubAllGlobals() }) test("getRuntimeContextWebWorker returns worker context", () => { class WorkerGlobalScopeMock { readonly internalType = "worker" } const selfWorker = new WorkerGlobalScopeMock() vi.stubGlobal("WorkerGlobalScope", WorkerGlobalScopeMock) vi.stubGlobal("ServiceWorkerGlobalScope", undefined) vi.stubGlobal("self", selfWorker) const context = Runtime.getRuntimeContextWebWorker() expect(context.self).toBe(selfWorker) vi.unstubAllGlobals() }) test("useWebWorker executes worker handler", () => { class WorkerGlobalScopeMock { readonly internalType = "worker" } const selfWorker = new WorkerGlobalScopeMock() vi.stubGlobal("WorkerGlobalScope", WorkerGlobalScopeMock) vi.stubGlobal("ServiceWorkerGlobalScope", undefined) vi.stubGlobal("self", selfWorker) vi.stubGlobal("process", undefined) vi.stubGlobal("window", undefined) const workerResult = Runtime.useWebWorker( (context) => typeof context.self === "object", () => false, ) expect(workerResult).toBe(true) vi.unstubAllGlobals() }) test("isServiceWorker detects service worker runtime", () => { class WorkerGlobalScopeMock { readonly internalType = "worker" } class ServiceWorkerGlobalScopeMock extends WorkerGlobalScopeMock { readonly internalTypeService = "service-worker" } vi.stubGlobal("WorkerGlobalScope", WorkerGlobalScopeMock) vi.stubGlobal("ServiceWorkerGlobalScope", ServiceWorkerGlobalScopeMock) vi.stubGlobal("self", new ServiceWorkerGlobalScopeMock()) vi.stubGlobal("process", undefined) vi.stubGlobal("window", undefined) expect(Runtime.isServiceWorker()).toBe(true) vi.unstubAllGlobals() }) test("getServiceWorkerContext returns service worker context", () => { class WorkerGlobalScopeMock { readonly internalType = "worker" } class ServiceWorkerGlobalScopeMock extends WorkerGlobalScopeMock { readonly internalTypeService = "service-worker" } const selfServiceWorker = new ServiceWorkerGlobalScopeMock() vi.stubGlobal("WorkerGlobalScope", WorkerGlobalScopeMock) vi.stubGlobal("ServiceWorkerGlobalScope", ServiceWorkerGlobalScopeMock) vi.stubGlobal("self", selfServiceWorker) const context = Runtime.getServiceWorkerContext() expect(context.self).toBe(selfServiceWorker) vi.unstubAllGlobals() }) test("useServiceWorker executes service worker handler", () => { class WorkerGlobalScopeMock { readonly internalType = "worker" } class ServiceWorkerGlobalScopeMock extends WorkerGlobalScopeMock { readonly internalTypeService = "service-worker" } const selfServiceWorker = new ServiceWorkerGlobalScopeMock() vi.stubGlobal("WorkerGlobalScope", WorkerGlobalScopeMock) vi.stubGlobal("ServiceWorkerGlobalScope", ServiceWorkerGlobalScopeMock) vi.stubGlobal("self", selfServiceWorker) vi.stubGlobal("process", undefined) vi.stubGlobal("window", undefined) const serviceWorkerResult = Runtime.useServiceWorker( (context) => typeof context.self === "object", () => false, ) expect(serviceWorkerResult).toBe(true) vi.unstubAllGlobals() }) test("isUnknown detects non-unknown runtime in current process", () => { expect(Runtime.isUnknown()).toBe(false) }) test("getRuntimeContextUnknown returns unknown context", () => { const context = Runtime.getRuntimeContextUnknown() expect(context.global).toBeUndefined() }) test("useUnknown executes fallback in current process", () => { const fallbackResult = Runtime.useUnknown( (context) => context.global, () => "fallback", ) expect(fallbackResult).toBe("fallback") }) test("getRuntimeRegistryItem returns matched runtime registry item", () => { const item = Runtime.getRuntimeRegistryItem() expect(item.runtime).toBe("nodejs") expect(typeof item.detect).toBe("function") }) test("getRuntime resolves current runtime key", () => { expect(Runtime.getRuntime()).toBe("nodejs") }) test("getRuntimeFlags resolves runtime detector outputs", () => { const flags = Runtime.getRuntimeFlags() expect(flags.browser).toBe(false) expect(flags.nodejs).toBe(true) expect(flags.unknown).toBe(false) }) test("isSatisfiesRuntime checks runtime and throws for missing", () => { expect(Runtime.isSatisfiesRuntime("nodejs")).toBe(true) expect(() => Runtime.isSatisfiesRuntime("runtime-not-found")).toThrow("is not registered") }) test("isSatisfiesRuntimes checks runtime conditions and throws for missing", () => { expect(Runtime.isSatisfiesRuntimes({ nodejs: true })).toBe(true) expect(Runtime.isSatisfiesRuntimes({ nodejs: false })).toBe(false) expect(() => Runtime.isSatisfiesRuntimes({ "runtime-not-found": true })).toThrow( "is not registered", ) }) test("useRuntimes executes runtime specific handler, default handler, and throws without handlers", () => { const nodeResult = Runtime.useRuntimes({ nodejs: () => "node", default: () => "default", }) const defaultResult = Runtime.useRuntimes({ browser: () => "browser", default: () => "default", }) expect(nodeResult).toBe("node") expect(defaultResult).toBe("default") expect(() => Runtime.useRuntimes({ browser: () => "browser" })).toThrow( "Neither runtime-specific nor default handler provided", ) })