diff --git a/components/Home/HomeRunRow.tsx b/components/Home/HomeRunRow.tsx index 3ecf555ed..2e029adf5 100644 --- a/components/Home/HomeRunRow.tsx +++ b/components/Home/HomeRunRow.tsx @@ -1,16 +1,17 @@ import Link from "next/link"; import { cn } from "@/lib/utils"; import type { TaskRunItem } from "@/lib/tasks/getTaskRuns"; -import { getTaskDisplayName } from "@/lib/tasks/getTaskDisplayName"; +import { getRunDisplayName } from "@/lib/tasks/getRunDisplayName"; import { getStatusColor } from "@/lib/tasks/getStatusColor"; import { getStatusLabel } from "@/lib/tasks/getStatusLabel"; import { formatTimestamp } from "@/lib/tasks/formatTimestamp"; /** * Compact task-run row for the homepage tasks module. Links to the - * existing run detail page. Per-run sent-email subjects are not exposed - * by `GET /api/tasks/runs` yet, so this shows what is available: run - * name, status, and finished-at (recoupable/chat#1850). + * existing run detail page. Renders the originating scheduled task's + * title when the api resolves one, falling back to the generic + * per-taskIdentifier label. Per-run sent-email subjects are not exposed + * by `GET /api/tasks/runs` yet (recoupable/chat#1850). */ const HomeRunRow = ({ run }: { run: TaskRunItem }) => ( ( >

- {getTaskDisplayName(run.taskIdentifier)} + {getRunDisplayName(run)}

{formatTimestamp(run.finishedAt ?? run.createdAt)} diff --git a/lib/tasks/__tests__/getRunDisplayName.test.ts b/lib/tasks/__tests__/getRunDisplayName.test.ts new file mode 100644 index 000000000..e2a225383 --- /dev/null +++ b/lib/tasks/__tests__/getRunDisplayName.test.ts @@ -0,0 +1,40 @@ +import { describe, it, expect } from "vitest"; +import { getRunDisplayName } from "../getRunDisplayName"; + +describe("getRunDisplayName", () => { + it("returns the run title when present", () => { + expect( + getRunDisplayName({ + title: "Weekly valuation + streams report", + taskIdentifier: "customer-prompt-task", + }), + ).toBe("Weekly valuation + streams report"); + }); + + it("falls back to the task display name when title is null", () => { + expect( + getRunDisplayName({ + title: null, + taskIdentifier: "customer-prompt-task", + }), + ).toBe("Scheduled Task"); + }); + + it("falls back to the task display name when title is absent (pre-title api)", () => { + expect(getRunDisplayName({ taskIdentifier: "customer-prompt-task" })).toBe( + "Scheduled Task", + ); + }); + + it("falls back to the task display name when title is empty", () => { + expect( + getRunDisplayName({ title: "", taskIdentifier: "setup-sandbox" }), + ).toBe("Setup Sandbox"); + }); + + it("falls back to the raw identifier for unmapped tasks without a title", () => { + expect( + getRunDisplayName({ title: null, taskIdentifier: "unknown-task" }), + ).toBe("unknown-task"); + }); +}); diff --git a/lib/tasks/getRunDisplayName.ts b/lib/tasks/getRunDisplayName.ts new file mode 100644 index 000000000..0861891c8 --- /dev/null +++ b/lib/tasks/getRunDisplayName.ts @@ -0,0 +1,13 @@ +import type { TaskRunItem } from "@/lib/tasks/getTaskRuns"; +import { getTaskDisplayName } from "@/lib/tasks/getTaskDisplayName"; + +/** + * Display name for a task run row: the originating scheduled task's title + * when the api resolved one, otherwise the generic per-taskIdentifier label + * (today's behavior — also the fallback until the api ships titles). + */ +export function getRunDisplayName( + run: Pick, +): string { + return run.title || getTaskDisplayName(run.taskIdentifier); +} diff --git a/lib/tasks/getTaskRuns.ts b/lib/tasks/getTaskRuns.ts index 11d3bf7d2..8c2aed8f3 100644 --- a/lib/tasks/getTaskRuns.ts +++ b/lib/tasks/getTaskRuns.ts @@ -7,6 +7,8 @@ export interface TaskRunItem { error?: string; metadata?: Record | null; taskIdentifier: string; + /** Originating scheduled task's title; null or absent when unresolvable. */ + title?: string | null; createdAt: string; startedAt: string | null; finishedAt: string | null;