Files
kandev/apps/web/lib/state/slices/comments/format.test.ts
T
José Almeida 3e237e177a feat: add agent-authored code walkthroughs (#1647)
* feat: add code-walkthrough backend (MCP tool, service, persistence, WS events)

* feat: render agent code walkthroughs as line-anchored cards + editor window

* test: add code-walkthrough re-emit mock-agent scenario

* fix: rework code-walkthrough UX (floating card, line reveal, minimize, clickable file)

* fix: improve code walkthrough editor UX

* fix: backfill walkthrough launcher after websocket connect

* fix: improve walkthrough requests and editor anchors

* fix: clear walkthrough highlights on close

* feat: add walkthrough discard and prompt customization

* fix: send walkthrough requests through saved prompt

* fix: support postgres built-in prompt seeding

* fix: address walkthrough review feedback

* fix: address walkthrough review follow-ups

* fix: harden walkthrough lifecycle races

* fix: reuse walkthrough notification cleanup

* fix: guard stale walkthrough file opens

* fix: abort stale file opens before paint

* fix: stabilize github settings e2e readiness

* fix: use stable github settings e2e selector
2026-07-10 08:34:57 +01:00

214 lines
6.6 KiB
TypeScript

import { describe, it, expect } from "vitest";
import {
formatPlanCommentsAsMarkdown,
formatReviewCommentsAsMarkdown,
formatPRFeedbackAsMarkdown,
formatWalkthroughCommentsAsMarkdown,
formatCommentsForMessage,
} from "./format";
import type { PlanComment, DiffComment, PRFeedbackComment, WalkthroughComment } from "./types";
function makePlanComment(overrides: Partial<PlanComment> = {}): PlanComment {
return {
id: "plan-1",
sessionId: "sess-1",
source: "plan",
text: "fix this",
selectedText: "some code",
createdAt: new Date().toISOString(),
status: "pending",
...overrides,
};
}
describe("formatPlanCommentsAsMarkdown", () => {
it("returns empty string for empty input", () => {
expect(formatPlanCommentsAsMarkdown([])).toBe("");
expect(formatPlanCommentsAsMarkdown(null as unknown as PlanComment[])).toBe("");
expect(formatPlanCommentsAsMarkdown(undefined as unknown as PlanComment[])).toBe("");
});
it("formats comment with selected text", () => {
const comments = [makePlanComment({ selectedText: "const x = 1;", text: "rename variable" })];
const result = formatPlanCommentsAsMarkdown(comments);
expect(result).toContain("### Plan Comments");
expect(result).toContain("```\nconst x = 1;\n```");
expect(result).toContain("> rename variable");
expect(result).toContain("---");
});
it("formats comment without selected text", () => {
const comments = [makePlanComment({ selectedText: "", text: "general feedback" })];
const result = formatPlanCommentsAsMarkdown(comments);
expect(result).toContain("### Plan Comments");
expect(result).not.toContain("```\n\n```"); // No empty code block
expect(result).toContain("> general feedback");
});
it("formats multiple comments", () => {
const comments = [
makePlanComment({ selectedText: "code1", text: "comment1" }),
makePlanComment({ id: "plan-2", selectedText: "code2", text: "comment2" }),
];
const result = formatPlanCommentsAsMarkdown(comments);
expect(result).toContain("```\ncode1\n```");
expect(result).toContain("> comment1");
expect(result).toContain("```\ncode2\n```");
expect(result).toContain("> comment2");
});
it("handles multiline comment text with blockquotes", () => {
const comments = [makePlanComment({ text: "line one\nline two\nline three" })];
const result = formatPlanCommentsAsMarkdown(comments);
expect(result).toContain("> line one\n> line two\n> line three");
});
it("includes header and separator", () => {
const comments = [makePlanComment()];
const result = formatPlanCommentsAsMarkdown(comments);
expect(result.startsWith("### Plan Comments\n")).toBe(true);
expect(result).toContain("\n---\n");
});
});
describe("formatReviewCommentsAsMarkdown", () => {
function makeDiffComment(overrides: Partial<DiffComment> = {}): DiffComment {
return {
id: "diff-1",
sessionId: "sess-1",
source: "diff",
filePath: "src/app.ts",
startLine: 10,
endLine: 12,
side: "additions",
codeContent: "const x = 1;",
text: "fix this",
createdAt: new Date().toISOString(),
status: "pending",
...overrides,
};
}
it("returns empty string for empty input", () => {
expect(formatReviewCommentsAsMarkdown([])).toBe("");
});
it("formats single comment", () => {
const result = formatReviewCommentsAsMarkdown([makeDiffComment()]);
expect(result).toContain("### Review Comments");
expect(result).toContain("**src/app.ts:10-12**");
expect(result).toContain("```\nconst x = 1;\n```");
expect(result).toContain("> fix this");
});
it("formats same-line range", () => {
const result = formatReviewCommentsAsMarkdown([makeDiffComment({ startLine: 5, endLine: 5 })]);
expect(result).toContain("**src/app.ts:5**");
});
});
describe("formatPRFeedbackAsMarkdown", () => {
function makePRFeedback(overrides: Partial<PRFeedbackComment> = {}): PRFeedbackComment {
return {
id: "pr-1",
sessionId: "sess-1",
source: "pr-feedback",
text: "",
prNumber: 123,
feedbackType: "review",
content: "Please fix the failing tests",
createdAt: new Date().toISOString(),
status: "pending",
...overrides,
};
}
it("returns empty string for empty input", () => {
expect(formatPRFeedbackAsMarkdown([])).toBe("");
});
it("formats PR feedback", () => {
const result = formatPRFeedbackAsMarkdown([makePRFeedback()]);
expect(result).toContain("### PR Feedback");
expect(result).toContain("Please fix the failing tests");
expect(result).toContain("---");
});
});
describe("formatWalkthroughCommentsAsMarkdown", () => {
function makeWalkthroughComment(overrides: Partial<WalkthroughComment> = {}): WalkthroughComment {
return {
id: "wtc-1",
sessionId: "sess-1",
source: "walkthrough",
taskId: "task-1",
walkthroughId: "wt-1",
walkthroughTitle: "Implementation tour",
stepIndex: 1,
stepCount: 4,
repo: "frontend",
filePath: "apps/web/main.ts",
startLine: 10,
endLine: 12,
stepText: "The agent explanation",
text: "Can you simplify this?",
createdAt: new Date().toISOString(),
status: "pending",
...overrides,
};
}
it("formats walkthrough feedback with step and anchor context", () => {
const result = formatWalkthroughCommentsAsMarkdown([makeWalkthroughComment()]);
expect(result).toContain("### Walkthrough Feedback");
expect(result).toContain("**Implementation tour · Step 2 / 4**");
expect(result).toContain("**frontend/apps/web/main.ts:10-12**");
expect(result).toContain("Agent walkthrough text:");
expect(result).toContain("> The agent explanation");
expect(result).toContain("User feedback:");
expect(result).toContain("> Can you simplify this?");
});
});
describe("formatCommentsForMessage", () => {
it("separates comments by type", () => {
const diff: DiffComment = {
id: "d1",
sessionId: "s",
source: "diff",
filePath: "f.ts",
startLine: 1,
endLine: 1,
side: "additions",
codeContent: "code",
text: "fix",
createdAt: "",
status: "pending",
};
const plan: PlanComment = {
id: "p1",
sessionId: "s",
source: "plan",
selectedText: "text",
text: "comment",
createdAt: "",
status: "pending",
};
const result = formatCommentsForMessage([diff, plan]);
expect(result.diffComments).toHaveLength(1);
expect(result.planComments).toHaveLength(1);
expect(result.prFeedbackComments).toHaveLength(0);
expect(result.walkthroughComments).toHaveLength(0);
});
});