Files
suaveplan/packages/gaming/games/ecs/src/system/system.test.ts
2026-05-27 23:47:53 +01:00

129 lines
4.0 KiB
TypeScript

import { describe, expect, it } from "@suaveplan/testing/runner";
import { defineComponent } from "../schema/schema.js";
import { defineSystem, SystemScheduler } from "./system.js";
const Position = defineComponent("Position", { x: 0 });
describe("defineSystem + SystemScheduler", () => {
it("defineSystem applies phase / priority / enabled defaults", {
timeout: 5000,
}, () => {
const sys = defineSystem({
name: "render",
query: { include: [Position] },
execute: () => undefined,
});
expect(sys.phase).toBe("update");
expect(sys.priority).toBe(0);
expect(sys.enabled).toBe(true);
});
it("defineSystem honors explicit values", { timeout: 5000 }, () => {
const sys = defineSystem({
name: "render",
phase: "render",
priority: 5,
enabled: false,
query: { include: [Position] },
execute: () => undefined,
});
expect(sys.phase).toBe("render");
expect(sys.priority).toBe(5);
expect(sys.enabled).toBe(false);
});
it("phases run in fixed order preUpdate update postUpdate render", {
timeout: 5000,
}, () => {
const scheduler = new SystemScheduler();
for (const phase of ["render", "preUpdate", "update"] as const) {
scheduler.add(
defineSystem({
name: phase,
phase,
query: { include: [Position] },
execute: () => undefined,
})
);
}
const names = scheduler.getOrdered().map((s) => s.name);
expect(names).toEqual(["preUpdate", "update", "render"]);
});
it("ties within a phase break by ascending priority", {
timeout: 5000,
}, () => {
const scheduler = new SystemScheduler();
scheduler.add(
defineSystem({
name: "B",
priority: 5,
query: { include: [Position] },
execute: () => undefined,
})
);
scheduler.add(
defineSystem({
name: "A",
priority: 2,
query: { include: [Position] },
execute: () => undefined,
})
);
const names = scheduler.getOrdered().map((s) => s.name);
expect(names).toEqual(["A", "B"]);
});
it("remove returns false for unknown system name", {
timeout: 5000,
}, () => {
const scheduler = new SystemScheduler();
expect(scheduler.remove("nope")).toBe(false);
});
it("remove returns true and shrinks the registered list", {
timeout: 5000,
}, () => {
const scheduler = new SystemScheduler();
scheduler.add(
defineSystem({
name: "A",
query: { include: [Position] },
execute: () => undefined,
})
);
expect(scheduler.remove("A")).toBe(true);
expect(scheduler.count).toBe(0);
});
it("has reports membership by name", { timeout: 5000 }, () => {
const scheduler = new SystemScheduler();
scheduler.add(
defineSystem({
name: "A",
query: { include: [Position] },
execute: () => undefined,
})
);
expect(scheduler.has("A")).toBe(true);
expect(scheduler.has("B")).toBe(false);
});
it("getAll returns a live read-only view, getOrdered returns a sorted view", {
timeout: 5000,
}, () => {
const scheduler = new SystemScheduler();
scheduler.add(
defineSystem({
name: "A",
query: { include: [Position] },
execute: () => undefined,
})
);
expect(scheduler.getAll().length).toBe(1);
expect(scheduler.getOrdered().length).toBe(1);
// calling again re-uses the sorted cache
expect(scheduler.getOrdered().length).toBe(1);
});
});