import { describe, expect, it } from "vitest"; import { summarizeHeartbeatRunResultJson, buildHeartbeatRunIssueComment, } from "../services/heartbeat-run-summary.js"; describe("summarizeHeartbeatRunResultJson", () => { it("truncates text fields and preserves cost aliases", () => { const summary = summarizeHeartbeatRunResultJson({ summary: "a".repeat(600), result: "ok", message: "done", error: "failed", total_cost_usd: 1.23, cost_usd: 0.45, costUsd: 0.67, nested: { ignored: true }, }); expect(summary).toEqual({ summary: "a".repeat(500), result: "ok", message: "done", error: "failed", total_cost_usd: 1.23, cost_usd: 0.45, costUsd: 0.67, }); }); it("returns null for non-object and irrelevant payloads", () => { expect(summarizeHeartbeatRunResultJson(null)).toBeNull(); expect(summarizeHeartbeatRunResultJson(["nope"] as unknown as Record)).toBeNull(); expect(summarizeHeartbeatRunResultJson({ nested: { only: "ignored" } })).toBeNull(); }); }); describe("buildHeartbeatRunIssueComment", () => { it("uses the final summary text for issue comments on successful runs", () => { const comment = buildHeartbeatRunIssueComment({ summary: "## Summary\n\n- fixed deploy config\n- posted issue update", }); expect(comment).toContain("## Summary"); expect(comment).toContain("- fixed deploy config"); expect(comment).not.toContain("Run summary"); }); it("falls back to result or message when summary is missing", () => { expect(buildHeartbeatRunIssueComment({ result: "done" })).toBe("done"); expect(buildHeartbeatRunIssueComment({ message: "completed" })).toBe("completed"); }); it("returns null when there is no usable final text", () => { expect(buildHeartbeatRunIssueComment({ costUsd: 1.2 })).toBeNull(); }); });