Files
OmniRoute/tests/unit/ui/orchestrationModel.test.ts
Diego Rodrigues de Sa e Souza d2a027a156 feat(dashboard): orchestration canvas fase 2 — quick wins + hardening (2.3/2.4/2.8/2.11/2.12, #12270, #12271) (#12393)
* feat(dashboard): orchestration pure snapshot filter (search + chips)

* feat(dashboard): orchestration collapse-by-source in flow projection

* refactor(dashboard): orchestration model polish (#12271 model items)

* feat(dashboard): theme-aware orchestration status tokens (2.12)

* feat(dashboard): particle StatusEdge for orchestration canvas (2.11)

* feat(dashboard): orchestration search/filter chips + collapse in URL (2.3+2.4)

* feat(dashboard): drawer trace copy + error/a11y hardening (2.8, #12270)

* chore(dashboard): orchestration UI hardening (#12270)

* fix(dashboard): type-safe source read in AgentsTab collapse handler

* fix(dashboard): pass staleSince into the sourceStale message

* test(dashboard): orchestration missing coverage + fase2 i18n (#12271)

* refactor(dashboard): split orchestration page/toolbar/drawer helpers under complexity ratchet

---------

Co-authored-by: Markus Hartung <diegosouzapw@users.noreply.github.com>
2026-09-01 23:13:47 -03:00

441 lines
18 KiB
TypeScript

/**
* tests/unit/ui/orchestrationModel.test.ts
* Run: node --import tsx/esm --test tests/unit/ui/orchestrationModel.test.ts
*/
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import {
ORCH_STATES,
orchStateColor,
orchStateBadgeBg,
} from "../../../src/app/(dashboard)/dashboard/orchestration/model/orchestrationTypes.ts";
import { fromCloudAgent } from "../../../src/app/(dashboard)/dashboard/orchestration/model/fromCloudAgent.ts";
import type { CloudAgentTask } from "../../../src/lib/cloudAgent/types.ts";
import { fromA2A } from "../../../src/app/(dashboard)/dashboard/orchestration/model/fromA2A.ts";
import type { A2ATask } from "../../../src/lib/a2a/taskManager.ts";
import { fromConductor } from "../../../src/app/(dashboard)/dashboard/orchestration/model/fromConductor.ts";
import type { FleetSnapshot } from "../../../src/lib/conductor/hubProxy.ts";
import { mergeSnapshot } from "../../../src/app/(dashboard)/dashboard/orchestration/model/mergeSnapshot.ts";
import {
STALE_COMPLETED_MS,
MAX_WORK_NODES,
} from "../../../src/app/(dashboard)/dashboard/orchestration/model/orchestrationTypes.ts";
describe("orchestrationTypes", () => {
it("covers all six states with a theme-aware CSS var color each", () => {
assert.equal(ORCH_STATES.length, 6);
for (const s of ORCH_STATES) {
assert.match(orchStateColor(s), /^var\(--orch-status-[a-z]+\)$/, s);
}
});
it("waiting_approval maps to the approval token", () => {
assert.equal(orchStateColor("waiting_approval"), "var(--orch-status-approval)");
});
it("running maps to warning, succeeded to success, failed to error", () => {
assert.equal(orchStateColor("running"), "var(--orch-status-warning)");
assert.equal(orchStateColor("succeeded"), "var(--orch-status-success)");
assert.equal(orchStateColor("failed"), "var(--orch-status-error)");
});
it("queued and cancelled both map to the muted token", () => {
assert.equal(orchStateColor("queued"), "var(--orch-status-muted)");
assert.equal(orchStateColor("cancelled"), "var(--orch-status-muted)");
});
it("orchStateBadgeBg produces a color-mix over the matching state token", () => {
for (const s of ORCH_STATES) {
const bg = orchStateBadgeBg(s);
assert.match(bg, /^color-mix\(in srgb, var\(--orch-status-[a-z]+\) 13%, transparent\)$/, s);
assert.ok(bg.includes(orchStateColor(s)), `${s} badge bg should embed its own token`);
}
});
});
function caTask(over: Partial<CloudAgentTask>): CloudAgentTask {
return {
id: "t1",
providerId: "devin",
status: "running",
prompt: "Fix the flaky test in CI",
source: { repoName: "acme/app", repoUrl: "https://github.com/acme/app" },
options: {},
activities: [],
createdAt: "2026-08-30T10:00:00Z",
updatedAt: "2026-08-30T10:05:00Z",
...over,
} as CloudAgentTask;
}
describe("fromCloudAgent", () => {
it("maps every status to the unified OrchState", () => {
const cases: Array<[CloudAgentTask["status"], string]> = [
["queued", "queued"],
["running", "running"],
["awaiting_approval", "waiting_approval"],
["completed", "succeeded"],
["failed", "failed"],
["cancelled", "cancelled"],
];
for (const [input, expected] of cases) {
const { nodes } = fromCloudAgent([caTask({ status: input })]);
const work = nodes.find((n) => n.kind === "work");
assert.equal(work?.state, expected, input);
}
});
it("unknown status becomes failed with the raw value in sublabel", () => {
const { nodes } = fromCloudAgent([caTask({ status: "exploded" as CloudAgentTask["status"] })]);
const work = nodes.find((n) => n.kind === "work");
assert.equal(work?.state, "failed");
assert.match(work?.sublabel ?? "", /exploded/);
});
it("running task with activities gets one ActivityNode; completed does not", () => {
const running = caTask({
activities: [
{ id: "a1", type: "command", content: "npm test", timestamp: "2026-08-30T10:04:00Z" },
],
});
const done = caTask({ id: "t2", status: "completed", activities: running.activities });
const { nodes, edges } = fromCloudAgent([running, done]);
const acts = nodes.filter((n) => n.kind === "activity");
assert.equal(acts.length, 1);
assert.equal(acts[0].id, "cloud-agent:t1:activity");
assert.ok(
edges.some(
(e) => e.from === "cloud-agent:t1" && e.to === "cloud-agent:t1:activity" && e.active
)
);
});
it("emits a SourceNode with per-state counts and owns-edges from it", () => {
const { nodes, edges } = fromCloudAgent([caTask({}), caTask({ id: "t2", status: "failed" })]);
const src = nodes.find((n) => n.id === "source:cloud-agent");
assert.equal(src?.counts?.running, 1);
assert.equal(src?.counts?.failed, 1);
assert.ok(
edges.some(
(e) => e.from === "source:cloud-agent" && e.to === "cloud-agent:t1" && e.kind === "owns"
)
);
});
it("empty input emits nothing", () => {
const out = fromCloudAgent([]);
assert.equal(out.nodes.length, 0);
assert.equal(out.edges.length, 0);
});
});
function a2aTask(over: Partial<A2ATask>): A2ATask {
return {
id: "a1",
skill: "smart-routing",
state: "working",
input: { skill: "smart-routing", messages: [{ role: "user", content: "route this well" }] },
artifacts: [],
events: [{ timestamp: "2026-08-30T10:00:00Z", state: "submitted" }],
metadata: {},
createdAt: "2026-08-30T10:00:00Z",
updatedAt: "2026-08-30T10:01:00Z",
expiresAt: "2026-08-30T10:05:00Z",
...over,
} as A2ATask;
}
describe("fromA2A", () => {
it("maps the five A2A states", () => {
const cases: Array<[A2ATask["state"], string]> = [
["submitted", "queued"],
["working", "running"],
["completed", "succeeded"],
["failed", "failed"],
["cancelled", "cancelled"],
];
for (const [input, expected] of cases) {
const { nodes } = fromA2A([a2aTask({ state: input })]);
assert.equal(nodes.find((n) => n.kind === "work")?.state, expected, input);
}
});
it("work node id is a2a:<id>, label is the skill", () => {
const { nodes } = fromA2A([a2aTask({})]);
const w = nodes.find((n) => n.kind === "work");
assert.equal(w?.id, "a2a:a1");
assert.equal(w?.label, "smart-routing");
});
it("empty input emits nothing", () => {
assert.equal(fromA2A([]).nodes.length, 0);
});
});
const baseSnap: FleetSnapshot = {
offline: false,
runners: [{ id: "r1", name: "runner-one", clis: ["claude"], online: true, draining: false }],
tasks: [
{
id: "ct1",
status: "running",
mode: "auto",
repo: "acme/app",
runner: "r1",
summary: "Refactor auth",
branch: null,
error: null,
updated_at: "2026-08-30T10:00:00Z",
},
],
};
describe("fromConductor", () => {
it("online runner with a running task → running WorkNode + ActivityNode for the task", () => {
const { nodes, edges } = fromConductor(baseSnap);
const runner = nodes.find((n) => n.id === "conductor:runner:r1");
assert.equal(runner?.state, "running");
const act = nodes.find((n) => n.id === "conductor:task:ct1");
assert.equal(act?.kind, "activity");
assert.ok(edges.some((e) => e.from === "conductor:runner:r1" && e.to === "conductor:task:ct1"));
});
it("queued task without runner hangs directly under the source as a work node", () => {
const snap: FleetSnapshot = {
...baseSnap,
runners: [],
tasks: [{ ...baseSnap.tasks[0], id: "ct2", status: "queued", runner: null }],
};
const { nodes, edges } = fromConductor(snap);
const w = nodes.find((n) => n.id === "conductor:task:ct2");
assert.equal(w?.kind, "work");
assert.equal(w?.state, "queued");
assert.ok(edges.some((e) => e.from === "source:conductor" && e.to === "conductor:task:ct2"));
});
it("offline snapshot emits only nothing (hook marks the source offline separately)", () => {
const out = fromConductor({ offline: true, runners: [], tasks: [] });
assert.equal(out.nodes.length, 0);
});
it("unknown hub status maps to failed with the raw value in sublabel", () => {
const snap: FleetSnapshot = {
...baseSnap,
runners: [],
tasks: [{ ...baseSnap.tasks[0], id: "ct3", status: "vaporized", runner: null }],
};
const w = fromConductor(snap).nodes.find((n) => n.id === "conductor:task:ct3");
assert.equal(w?.state, "failed");
assert.match(w?.sublabel ?? "", /vaporized/);
});
it("running task whose runner is not present in snap.runners is emitted as a work node, not swallowed", () => {
const snap: FleetSnapshot = {
offline: false,
runners: [],
tasks: [
{
...baseSnap.tasks[0],
id: "ct-orphan",
status: "running",
runner: "ghost-runner",
},
],
};
const { nodes, edges } = fromConductor(snap);
const w = nodes.find((n) => n.id === "conductor:task:ct-orphan");
assert.equal(w?.kind, "work");
assert.equal(w?.state, "running");
assert.ok(
edges.some((e) => e.from === "source:conductor" && e.to === "conductor:task:ct-orphan")
);
});
});
const OK_SOURCES = [
{ source: "cloud-agent" as const, ok: true },
{ source: "a2a" as const, ok: true },
{ source: "conductor" as const, ok: true },
];
const NOW = Date.parse("2026-08-30T12:00:00Z");
const empty = { nodes: [], edges: [] };
describe("mergeSnapshot", () => {
it("adds the orchestrator root and root→source edges", () => {
const snap = mergeSnapshot(
{ cloudAgent: fromCloudAgent([caTask({})]), a2a: empty, conductor: empty },
OK_SOURCES,
{ now: NOW }
);
assert.ok(snap.nodes.some((n) => n.id === "orchestrator"));
assert.ok(snap.edges.some((e) => e.from === "orchestrator" && e.to === "source:cloud-agent"));
});
it("dedupes a Conductor-mirrored A2A task into one node with a mirror edge", () => {
const a2a = fromA2A([
a2aTask({ id: "am1", skill: "conductor", metadata: { conductor: { task_id: "ct1" } } }),
]);
const conductor = fromConductor(baseSnap); // contains conductor:task:ct1 as activity of r1
const snap = mergeSnapshot({ cloudAgent: empty, a2a, conductor }, OK_SOURCES, { now: NOW });
assert.ok(
!snap.nodes.some((n) => n.id === "a2a:am1"),
"mirrored A2A work node must be dropped"
);
const mirrorEdge = snap.edges.find((e) => e.kind === "mirror");
assert.equal(mirrorEdge?.to, "source:a2a");
});
it("drops terminal work older than STALE_COMPLETED_MS unless showCompleted", () => {
const old = caTask({
id: "old",
status: "completed",
completedAt: new Date(NOW - STALE_COMPLETED_MS - 1000).toISOString(),
});
const parts = { cloudAgent: fromCloudAgent([old]), a2a: empty, conductor: empty };
assert.ok(
!mergeSnapshot(parts, OK_SOURCES, { now: NOW }).nodes.some((n) => n.id === "cloud-agent:old")
);
assert.ok(
mergeSnapshot(parts, OK_SOURCES, { now: NOW, showCompleted: true }).nodes.some(
(n) => n.id === "cloud-agent:old"
)
);
});
it("caps work nodes at MAX_WORK_NODES with a per-source overflow node", () => {
const many = Array.from({ length: MAX_WORK_NODES + 10 }, (_, i) =>
caTask({ id: `m${i}`, updatedAt: new Date(NOW - i * 1000).toISOString() })
);
const snap = mergeSnapshot(
{ cloudAgent: fromCloudAgent(many), a2a: empty, conductor: empty },
OK_SOURCES,
{ now: NOW }
);
const works = snap.nodes.filter((n) => n.kind === "work");
assert.ok(works.length <= MAX_WORK_NODES, `got ${works.length}`);
const overflow = snap.nodes.find((n) => n.id === "overflow:cloud-agent");
assert.ok(overflow, "overflow node expected");
});
it("keeps SourceStatus[] verbatim on the snapshot", () => {
const src = [{ source: "conductor" as const, ok: false, offline: true }];
const snap = mergeSnapshot({ cloudAgent: empty, a2a: empty, conductor: empty }, src, {
now: NOW,
});
assert.deepEqual(snap.sources, src);
});
it("does not mutate input node objects when deduping (honors the Pure contract)", () => {
const a2a = fromA2A([
a2aTask({ id: "am2", skill: "conductor", metadata: { conductor: { task_id: "ct1" } } }),
]);
const conductor = fromConductor(baseSnap); // contains conductor:task:ct1 as activity of r1
const originalNode = conductor.nodes.find((n) => n.id === "conductor:task:ct1");
assert.ok(originalNode, "conductor:task:ct1 must exist in the source part");
const snap = mergeSnapshot({ cloudAgent: empty, a2a, conductor }, OK_SOURCES, { now: NOW });
assert.equal(
"mirrorOf" in (originalNode as object),
false,
"the original conductor input node must not be mutated"
);
const mergedNode = snap.nodes.find((n) => n.id === "conductor:task:ct1");
assert.equal(mergedNode?.mirrorOf, "a2a:am2");
});
it("materializes an offline placeholder source node for a source reporting offline:true even when ok:true", () => {
const src = [{ source: "conductor" as const, ok: true, offline: true }];
const snap = mergeSnapshot({ cloudAgent: empty, a2a: empty, conductor: empty }, src, {
now: NOW,
});
const node = snap.nodes.find((n) => n.id === "source:conductor");
assert.ok(node, "offline placeholder source:conductor node expected");
assert.equal(node?.sublabel, "offline");
assert.ok(
snap.edges.some(
(e) => e.from === "orchestrator" && e.to === "source:conductor" && e.kind === "owns"
)
);
});
it("failed source placeholder carries the typed sourceIssue union alongside sublabel", () => {
const errSrc = [{ source: "conductor" as const, ok: false }];
const errSnap = mergeSnapshot({ cloudAgent: empty, a2a: empty, conductor: empty }, errSrc, {
now: NOW,
});
const errNode = errSnap.nodes.find((n) => n.id === "source:conductor");
assert.equal(errNode?.sourceIssue, "error");
assert.equal(errNode?.sublabel, "error");
const offlineSrc = [{ source: "conductor" as const, ok: true, offline: true }];
const offlineSnap = mergeSnapshot(
{ cloudAgent: empty, a2a: empty, conductor: empty },
offlineSrc,
{ now: NOW }
);
const offlineNode = offlineSnap.nodes.find((n) => n.id === "source:conductor");
assert.equal(offlineNode?.sourceIssue, "offline");
assert.equal(offlineNode?.sublabel, "offline");
});
it("failed source placeholder carries staleSince from the SourceStatus (undefined when the status has none)", () => {
const staleSince = "2026-09-01T12:00:00.000Z";
const errSrc = [{ source: "conductor" as const, ok: false, staleSince }];
const errSnap = mergeSnapshot({ cloudAgent: empty, a2a: empty, conductor: empty }, errSrc, {
now: NOW,
});
const errNode = errSnap.nodes.find((n) => n.id === "source:conductor");
assert.equal(errNode?.staleSince, staleSince);
// buildSourceStatuses never sets staleSince for the offline case — mergeSnapshot must
// not invent one, so the placeholder node's staleSince stays undefined.
const offlineSrc = [{ source: "conductor" as const, ok: true, offline: true }];
const offlineSnap = mergeSnapshot(
{ cloudAgent: empty, a2a: empty, conductor: empty },
offlineSrc,
{ now: NOW }
);
const offlineNode = offlineSnap.nodes.find((n) => n.id === "source:conductor");
assert.equal(offlineNode?.staleSince, undefined);
});
it("overflow node carries droppedByState with the per-state counts of dropped work nodes", () => {
const many = Array.from({ length: MAX_WORK_NODES + 5 }, (_, i) =>
caTask({
id: `ov${i}`,
status: i < MAX_WORK_NODES ? "running" : "failed",
updatedAt: new Date(NOW - i * 1000).toISOString(),
})
);
const snap = mergeSnapshot(
{ cloudAgent: fromCloudAgent(many), a2a: empty, conductor: empty },
OK_SOURCES,
{ now: NOW }
);
const overflow = snap.nodes.find((n) => n.id === "overflow:cloud-agent");
assert.ok(overflow, "overflow node expected");
assert.deepEqual(overflow?.droppedByState, { failed: 5 });
});
it("droppedByState is not a shared reference with counts — mutating counts after merge leaves it untouched", () => {
const many = Array.from({ length: MAX_WORK_NODES + 5 }, (_, i) =>
caTask({
id: `dbs${i}`,
status: i < MAX_WORK_NODES ? "running" : "failed",
updatedAt: new Date(NOW - i * 1000).toISOString(),
})
);
const snap = mergeSnapshot(
{ cloudAgent: fromCloudAgent(many), a2a: empty, conductor: empty },
OK_SOURCES,
{ now: NOW }
);
const overflow = snap.nodes.find((n) => n.id === "overflow:cloud-agent");
assert.ok(overflow, "overflow node expected");
const before = { ...overflow?.droppedByState };
if (overflow?.counts) overflow.counts.failed = 999;
assert.deepEqual(overflow?.droppedByState, before, "droppedByState must not alias counts");
});
it("drops a stale terminal Conductor task older than STALE_COMPLETED_MS unless showCompleted", () => {
const staleSnap: FleetSnapshot = {
...baseSnap,
runners: [],
tasks: [
{
...baseSnap.tasks[0],
id: "ctOld",
status: "completed",
runner: null,
updated_at: new Date(NOW - STALE_COMPLETED_MS - 1000).toISOString(),
},
],
};
const parts = { cloudAgent: empty, a2a: empty, conductor: fromConductor(staleSnap) };
assert.ok(
!mergeSnapshot(parts, OK_SOURCES, { now: NOW }).nodes.some(
(n) => n.id === "conductor:task:ctOld"
)
);
assert.ok(
mergeSnapshot(parts, OK_SOURCES, { now: NOW, showCompleted: true }).nodes.some(
(n) => n.id === "conductor:task:ctOld"
)
);
});
});