77 lines
4.0 KiB
TypeScript
77 lines
4.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import type { CatalogComponent, FlowDefinition } from "../../src/types";
|
|
import { register } from "../../src/engine/registry";
|
|
import { runFlow } from "../../src/engine/runtime";
|
|
|
|
const components = new Map<string, CatalogComponent>();
|
|
function component(id: string): CatalogComponent {
|
|
const value = {
|
|
id, name: id, kind: "vendor", group: "data", categories: [], categorySignature: "", description: "",
|
|
messageTemplate: "", baseType: id, functionName: id, functionCalls: [], version: "", tags: [], platformTag: null,
|
|
icon: "data", risk: "low", fields: [], output: { label: "", key: "", suggestedName: "", valueTypes: [], fields: [] }, slots: []
|
|
} as unknown as CatalogComponent;
|
|
components.set(id, value);
|
|
return value;
|
|
}
|
|
|
|
for (const id of ["Test.Start", "Test.Fail", "Test.Normal", "Test.Recover"]) component(id);
|
|
register("Test.Start", () => true);
|
|
register("Test.Fail", () => { throw new Error("expected failure"); });
|
|
register("Test.Normal", (ctx) => { ctx.vars.normalRan = true; });
|
|
register("Test.Recover", (ctx) => { ctx.vars.recovered = true; });
|
|
|
|
describe("runtime error route", () => {
|
|
it("uses the error handle after failure and does not execute the normal branch", async () => {
|
|
const now = new Date().toISOString();
|
|
const flow: FlowDefinition = {
|
|
schemaVersion: 1, id: "error-route", name: "error route", variables: [],
|
|
nodes: [
|
|
{ id: "start", componentId: "Test.Start", position: { x: 0, y: 0 }, values: {}, options: {} },
|
|
{ id: "fail", componentId: "Test.Fail", position: { x: 0, y: 100 }, values: {}, options: { errorRouteEnabled: true } },
|
|
{ id: "normal", componentId: "Test.Normal", position: { x: 0, y: 200 }, values: {}, options: {} },
|
|
{ id: "recover", componentId: "Test.Recover", position: { x: 200, y: 100 }, values: {}, options: {} }
|
|
],
|
|
edges: [
|
|
{ id: "e1", source: "start", target: "fail" },
|
|
{ id: "e2", source: "fail", target: "normal" },
|
|
{ id: "e3", source: "fail", sourceHandle: "error", target: "recover" }
|
|
],
|
|
meta: { createdAt: now, updatedAt: now, appVersion: "test" }
|
|
};
|
|
const result = await runFlow(flow, {
|
|
runId: "test", evidenceDir: ".", signal: new AbortController().signal,
|
|
emit: () => {}, log: () => {}, componentOf: (node) => components.get(node.componentId)
|
|
});
|
|
expect(result.status).toBe("succeeded");
|
|
expect(result.variables.recovered).toBe(true);
|
|
expect(result.variables.normalRan).toBeUndefined();
|
|
expect(result.variables.error).toMatchObject({ reason: "expected failure" });
|
|
});
|
|
|
|
it("uses the normal handle after success and leaves error and disconnected nodes untouched", async () => {
|
|
const now = new Date().toISOString();
|
|
const flow: FlowDefinition = {
|
|
schemaVersion: 1, id: "normal-route", name: "normal route", variables: [],
|
|
nodes: [
|
|
{ id: "start", componentId: "Test.Start", position: { x: 0, y: 0 }, values: {}, options: {} },
|
|
{ id: "normal", componentId: "Test.Normal", position: { x: 0, y: 100 }, values: {}, options: {} },
|
|
{ id: "recover", componentId: "Test.Recover", position: { x: 200, y: 0 }, values: {}, options: {} },
|
|
{ id: "orphan", componentId: "Test.Recover", position: { x: 400, y: 400 }, values: {}, options: {} }
|
|
],
|
|
edges: [
|
|
{ id: "e1", source: "start", target: "normal" },
|
|
{ id: "e2", source: "start", sourceHandle: "error", target: "recover" }
|
|
],
|
|
meta: { createdAt: now, updatedAt: now, appVersion: "test" }
|
|
};
|
|
const result = await runFlow(flow, {
|
|
runId: "test", evidenceDir: ".", signal: new AbortController().signal,
|
|
emit: () => {}, log: () => {}, componentOf: (node) => components.get(node.componentId)
|
|
});
|
|
expect(result.status).toBe("succeeded");
|
|
expect(result.variables.normalRan).toBe(true);
|
|
expect(result.variables.recovered).toBeUndefined();
|
|
expect(result.nodes.map((state) => state.nodeId)).toEqual(["start", "normal"]);
|
|
});
|
|
});
|