import { describe, expect, it, vi } from "vitest"; import { RuntimeEvents } from "@/kernel/RuntimeEvents"; import { AppRuntime } from "@/kernel/AppRuntime"; import type { RuntimePlugin } from "@/kernel/RuntimePlugin"; vi.mock("@/core/Game", () => { class MockGame { private static instance: MockGame; static getInstance(): MockGame { if (!MockGame.instance) { MockGame.instance = new MockGame(); } return MockGame.instance; } } return { default: MockGame }; }); vi.mock("@/scene/SceneManager", () => { class MockSceneManager { private static instance: MockSceneManager; static getInstance(): MockSceneManager { if (!MockSceneManager.instance) { MockSceneManager.instance = new MockSceneManager(); } return MockSceneManager.instance; } } return { default: MockSceneManager }; }); describe("RuntimeEvents", () => { it("supports on/off/emit", () => { const events = new RuntimeEvents(); const handler = vi.fn(); events.on("runtime:ready", handler); events.emit("runtime:ready", { startedAt: 1 }); events.off("runtime:ready", handler); events.emit("runtime:ready", { startedAt: 2 }); expect(handler).toHaveBeenCalledTimes(1); expect(handler).toHaveBeenCalledWith({ startedAt: 1 }); }); it("supports once subscriptions", () => { const events = new RuntimeEvents(); const handler = vi.fn(); events.once("scene:changed", handler); events.emit("scene:changed", { current: "a", previous: undefined }); events.emit("scene:changed", { current: "b", previous: "a" }); expect(handler).toHaveBeenCalledTimes(1); expect(handler).toHaveBeenCalledWith({ current: "a", previous: undefined }); }); }); describe("AppRuntime plugin lifecycle", () => { it("installs plugin and keeps compatibility exports", () => { const runtime = new AppRuntime(); const setup = vi.fn(); const plugin: RuntimePlugin = { name: "test-plugin", setup, }; runtime.use(plugin); runtime.use(plugin); expect(setup).toHaveBeenCalledTimes(1); expect(runtime.game).toBeDefined(); expect(runtime.sceneManager).toBeDefined(); expect(runtime.events).toBeDefined(); }); });