Files
kandev/apps/web/components/task/session-sort.test.ts
T
2026-05-17 20:16:15 +01:00

123 lines
4.1 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
buildAgentLabelsById,
isSessionActive,
pickActiveSessionId,
resolveAgentLabelFor,
sortSessions,
} from "./session-sort";
import {
agentProfileId as toAgentProfileId,
sessionId as toSessionId,
taskId as toTaskId,
type TaskSession,
type TaskSessionState,
} from "@/lib/types/http";
const EPOCH = "2025-01-01T00:00:00Z";
type SessionOverrides = Partial<Omit<TaskSession, "id" | "task_id" | "agent_profile_id">> & {
id?: string;
task_id?: string;
agent_profile_id?: string;
};
function makeSession(overrides: SessionOverrides): TaskSession {
const { id, task_id, agent_profile_id, ...rest } = overrides;
return {
id: toSessionId(id ?? "s1"),
task_id: toTaskId(task_id ?? "t1"),
...(agent_profile_id !== undefined
? { agent_profile_id: toAgentProfileId(agent_profile_id) }
: {}),
environment_id: "e1",
state: "CREATED" as TaskSessionState,
started_at: EPOCH,
updated_at: EPOCH,
...rest,
} as TaskSession;
}
describe("sortSessions", () => {
it("orders running sessions before completed ones", () => {
const sessions = [
makeSession({ id: "done", state: "COMPLETED", started_at: "2025-01-05T00:00:00Z" }),
makeSession({ id: "run", state: "RUNNING", started_at: "2025-01-01T00:00:00Z" }),
];
expect(sortSessions(sessions).map((s) => s.id)).toEqual(["run", "done"]);
});
it("breaks ties by most recent started_at", () => {
const sessions = [
makeSession({ id: "old", state: "RUNNING", started_at: "2025-01-01T00:00:00Z" }),
makeSession({ id: "new", state: "RUNNING", started_at: "2025-01-05T00:00:00Z" }),
];
expect(sortSessions(sessions).map((s) => s.id)).toEqual(["new", "old"]);
});
});
describe("resolveAgentLabelFor", () => {
it("prefers the current store label when the profile still exists", () => {
const session = makeSession({
agent_profile_id: "p1",
agent_profile_snapshot: { label: "Snapshot Agent" },
});
const labels = buildAgentLabelsById([{ id: "p1", label: "Store Agent" } as never]);
expect(resolveAgentLabelFor(session, labels)).toBe("Store Agent");
});
it("falls back to snapshot label when the profile is no longer in the store", () => {
const session = makeSession({
agent_profile_id: "deleted",
agent_profile_snapshot: { label: "Snapshot Agent" },
});
expect(resolveAgentLabelFor(session, {})).toBe("Snapshot Agent");
});
it("returns 'Unknown agent' when both are missing", () => {
const session = makeSession({ agent_profile_id: "missing" });
expect(resolveAgentLabelFor(session, {})).toBe("Unknown agent");
});
});
describe("pickActiveSessionId", () => {
it("returns null for an empty list", () => {
expect(pickActiveSessionId([], "anything")).toBeNull();
});
it("honors a preferred session when it exists", () => {
const sessions = [makeSession({ id: "a" }), makeSession({ id: "b", is_primary: true })];
expect(pickActiveSessionId(sessions, "a")).toBe("a");
});
it("ignores the preferred session when not present and falls back to primary", () => {
const sessions = [makeSession({ id: "a" }), makeSession({ id: "b", is_primary: true })];
expect(pickActiveSessionId(sessions, "missing")).toBe("b");
});
it("falls back to the first session when no primary exists", () => {
const sessions = [makeSession({ id: "a" }), makeSession({ id: "b" })];
expect(pickActiveSessionId(sessions, null)).toBe("a");
});
});
describe("isSessionActive", () => {
it("is true while the agent is starting or running", () => {
expect(isSessionActive("RUNNING")).toBe(true);
expect(isSessionActive("STARTING")).toBe(true);
});
it("is false for terminal and idle states", () => {
expect(isSessionActive("WAITING_FOR_INPUT")).toBe(false);
expect(isSessionActive("COMPLETED")).toBe(false);
expect(isSessionActive("FAILED")).toBe(false);
expect(isSessionActive("CANCELLED")).toBe(false);
expect(isSessionActive("CREATED")).toBe(false);
});
it("is false for null/undefined", () => {
expect(isSessionActive(null)).toBe(false);
expect(isSessionActive(undefined)).toBe(false);
});
});