Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,180 @@
import { describe, expect, it } from "@suaveplan/testing/runner";
import { FSM_CODES, FSMError } from "../errors/fsm-error.js";
import { validateDefinition } from "./definition-validator.js";
describe("validateDefinition", () => {
it("accepts a valid minimal definition", { timeout: 5000 }, () => {
expect(() =>
validateDefinition({
initial: "idle",
context: {},
states: { idle: {} },
})
).not.toThrow();
});
it("accepts a valid multi-state definition", { timeout: 5000 }, () => {
expect(() =>
validateDefinition({
initial: "red",
context: {},
states: {
red: { on: { NEXT: { target: "green" } } },
green: { on: { NEXT: { target: "yellow" } } },
yellow: { on: { NEXT: { target: "red" } } },
},
})
).not.toThrow();
});
it("throws INVALID_DEFINITION when initial state does not exist", {
timeout: 5000,
}, () => {
let err: FSMError | undefined;
try {
validateDefinition({
initial: "ghost",
context: {},
states: { idle: {} },
});
} catch (e) {
err = e as FSMError;
}
expect(err).toBeInstanceOf(FSMError);
expect(err?.code).toBe(FSM_CODES.INVALID_DEFINITION);
expect(err?.message).toContain("ghost");
});
it("throws INVALID_DEFINITION when transition targets non-existent state", {
timeout: 5000,
}, () => {
let err: FSMError | undefined;
try {
validateDefinition({
initial: "idle",
context: {},
states: {
idle: { on: { GO: { target: "nowhere" } } },
},
});
} catch (e) {
err = e as FSMError;
}
expect(err).toBeInstanceOf(FSMError);
expect(err?.code).toBe(FSM_CODES.INVALID_DEFINITION);
expect(err?.message).toContain("nowhere");
});
it("accepts multiple transition candidates for the same event", {
timeout: 5000,
}, () => {
expect(() =>
validateDefinition({
initial: "idle",
context: { count: 0 },
states: {
idle: {
on: {
GO: [{ target: "active" }, { target: "inactive" }],
},
},
active: {},
inactive: {},
},
})
).not.toThrow();
});
it("throws when nested initial child does not exist", {
timeout: 5000,
}, () => {
let err: FSMError | undefined;
try {
validateDefinition({
initial: "form",
context: {},
states: {
form: {
initial: "step999",
states: {
step1: {},
},
},
},
});
} catch (e) {
err = e as FSMError;
}
expect(err).toBeInstanceOf(FSMError);
expect(err?.code).toBe(FSM_CODES.INVALID_DEFINITION);
expect(err?.message).toContain("step999");
});
it("throws when nested states exist but no initial is declared", {
timeout: 5000,
}, () => {
let err: FSMError | undefined;
try {
validateDefinition({
initial: "form",
context: {},
states: {
form: {
states: {
step1: {},
},
// initial deliberately omitted
},
},
});
} catch (e) {
err = e as FSMError;
}
expect(err).toBeInstanceOf(FSMError);
expect(err?.code).toBe(FSM_CODES.INVALID_DEFINITION);
});
it("accepts a valid nested definition with correct initial", {
timeout: 5000,
}, () => {
expect(() =>
validateDefinition({
initial: "form",
context: {},
states: {
form: {
initial: "step1",
states: {
step1: { on: { NEXT: { target: "step2" } } },
step2: {},
},
},
},
})
).not.toThrow();
});
it("throws when a transition target in nested states is unknown", {
timeout: 5000,
}, () => {
let err: FSMError | undefined;
try {
validateDefinition({
initial: "form",
context: {},
states: {
form: {
initial: "step1",
states: {
step1: { on: { GO: { target: "ghost" } } },
},
},
},
});
} catch (e) {
err = e as FSMError;
}
expect(err).toBeInstanceOf(FSMError);
expect(err?.code).toBe(FSM_CODES.INVALID_DEFINITION);
});
});