93 lines
3.1 KiB
TypeScript
93 lines
3.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { deriveProjectDisplayName, deriveRemoteProjectKey, groupAgents } from "./agent-grouping";
|
|
import type { AggregatedAgent } from "@/hooks/use-aggregated-agents";
|
|
|
|
function makeAgent(overrides: Partial<AggregatedAgent> = {}): AggregatedAgent {
|
|
const now = new Date();
|
|
return {
|
|
id: overrides.id ?? "a1",
|
|
serverId: overrides.serverId ?? "s1",
|
|
serverLabel: (overrides as any).serverLabel ?? "server",
|
|
title: overrides.title ?? null,
|
|
status: overrides.status ?? ("running" as AggregatedAgent["status"]),
|
|
lastActivityAt: overrides.lastActivityAt ?? now,
|
|
cwd: overrides.cwd ?? "/tmp/repo",
|
|
provider: overrides.provider ?? ("openai" as any),
|
|
requiresAttention: overrides.requiresAttention ?? false,
|
|
attentionReason: overrides.attentionReason ?? null,
|
|
attentionTimestamp: overrides.attentionTimestamp ?? null,
|
|
} as AggregatedAgent;
|
|
}
|
|
|
|
describe("deriveRemoteProjectKey", () => {
|
|
it("normalizes GitHub SSH and HTTPS to the same key", () => {
|
|
const ssh = "git@github.com:owner/repo.git";
|
|
const https = "https://github.com/owner/repo";
|
|
expect(deriveRemoteProjectKey(ssh)).toBe("remote:github.com/owner/repo");
|
|
expect(deriveRemoteProjectKey(https)).toBe("remote:github.com/owner/repo");
|
|
});
|
|
|
|
it("includes host for non-GitHub remotes", () => {
|
|
const gitlab = "git@gitlab.example.com:group/repo.git";
|
|
expect(deriveRemoteProjectKey(gitlab)).toBe("remote:gitlab.example.com/group/repo");
|
|
});
|
|
});
|
|
|
|
describe("deriveProjectDisplayName", () => {
|
|
it("shows owner/repo for GitHub remote keys", () => {
|
|
expect(
|
|
deriveProjectDisplayName({
|
|
projectKey: "remote:github.com/getpaseo/paseo",
|
|
projectName: "paseo",
|
|
}),
|
|
).toBe("getpaseo/paseo");
|
|
});
|
|
|
|
it("shows remote path for non-GitHub remote keys", () => {
|
|
expect(
|
|
deriveProjectDisplayName({
|
|
projectKey: "remote:gitlab.example.com/group/repo",
|
|
projectName: "repo",
|
|
}),
|
|
).toBe("group/repo");
|
|
});
|
|
|
|
it("falls back to projectName for local keys", () => {
|
|
expect(
|
|
deriveProjectDisplayName({
|
|
projectKey: "/Users/me/dev/paseo",
|
|
projectName: "paseo",
|
|
}),
|
|
).toBe("paseo");
|
|
});
|
|
});
|
|
|
|
describe("groupAgents", () => {
|
|
it("groups active agents by remote URL when available", () => {
|
|
const agents = [
|
|
makeAgent({ id: "a1", cwd: "/Users/me/dev/paseo" }),
|
|
makeAgent({ id: "a2", cwd: "/Users/me/dev/paseo-fix/worktree" }),
|
|
];
|
|
|
|
const { activeGroups } = groupAgents(agents, {
|
|
getRemoteUrl: () => "git@github.com:getpaseo/paseo.git",
|
|
});
|
|
|
|
expect(activeGroups).toHaveLength(1);
|
|
expect(activeGroups[0]?.agents.map((a) => a.id).sort()).toEqual(["a1", "a2"]);
|
|
});
|
|
|
|
it("falls back to cwd grouping when remote URL is unavailable", () => {
|
|
const agents = [
|
|
makeAgent({ id: "a1", cwd: "/Users/me/dev/paseo" }),
|
|
makeAgent({ id: "a2", cwd: "/Users/me/dev/paseo-fix/worktree" }),
|
|
];
|
|
|
|
const { activeGroups } = groupAgents(agents, {
|
|
getRemoteUrl: () => null,
|
|
});
|
|
|
|
expect(activeGroups).toHaveLength(2);
|
|
});
|
|
});
|