test comment deletion cleanup regressions

This commit is contained in:
Dotta
2026-06-03 17:39:42 +00:00
parent 1afc8b1a60
commit d87b14ff4f
2 changed files with 40 additions and 5 deletions
+14 -5
View File
@@ -1,6 +1,7 @@
// @vitest-environment jsdom // @vitest-environment jsdom
import { act, createRef, forwardRef, useImperativeHandle, useState } from "react"; import { act, createRef, forwardRef, useImperativeHandle, useState } from "react";
import { flushSync } from "react-dom";
import type { ReactNode } from "react"; import type { ReactNode } from "react";
import { createRoot } from "react-dom/client"; import { createRoot } from "react-dom/client";
import { MemoryRouter } from "react-router-dom"; import { MemoryRouter } from "react-router-dom";
@@ -33,6 +34,14 @@ import type {
IssueChatTranscriptEntry, IssueChatTranscriptEntry,
} from "../lib/issue-chat-messages"; } from "../lib/issue-chat-messages";
function flushAct<T>(callback: () => T): T {
let result: T | undefined;
flushSync(() => {
result = callback();
});
return result as T;
}
function hasSmoothScrollBehavior(arg: unknown) { function hasSmoothScrollBehavior(arg: unknown) {
return typeof arg === "object" return typeof arg === "object"
&& arg !== null && arg !== null
@@ -1327,7 +1336,7 @@ describe("IssueChatThread", () => {
it("renders deleted comments as tombstones without the original body", () => { it("renders deleted comments as tombstones without the original body", () => {
const root = createRoot(container); const root = createRoot(container);
act(() => { flushAct(() => {
root.render( root.render(
<MemoryRouter> <MemoryRouter>
<IssueChatThread <IssueChatThread
@@ -1360,12 +1369,12 @@ describe("IssueChatThread", () => {
); );
}); });
expect(container.textContent).toContain("Comment deleted"); expect(container.textContent).toContain("You deleted this comment");
expect(container.textContent).not.toContain("Sensitive deleted body"); expect(container.textContent).not.toContain("Sensitive deleted body");
expect(container.querySelector("button[aria-label='Delete comment']")).toBeNull(); expect(container.querySelector("button[aria-label='Delete comment']")).toBeNull();
expect(container.querySelector("button[aria-label='Copy message']")).toBeNull(); expect(container.querySelector("button[aria-label='Copy message']")).toBeNull();
act(() => { flushAct(() => {
root.unmount(); root.unmount();
}); });
}); });
@@ -1374,7 +1383,7 @@ describe("IssueChatThread", () => {
const root = createRoot(container); const root = createRoot(container);
const replaceStateSpy = vi.spyOn(window.history, "replaceState").mockImplementation(() => {}); const replaceStateSpy = vi.spyOn(window.history, "replaceState").mockImplementation(() => {});
act(() => { flushAct(() => {
root.render( root.render(
<MemoryRouter initialEntries={["/issues/PAP-1#comment-comment-deleted"]}> <MemoryRouter initialEntries={["/issues/PAP-1#comment-comment-deleted"]}>
<IssueChatThread <IssueChatThread
@@ -1409,7 +1418,7 @@ describe("IssueChatThread", () => {
expect(replaceStateSpy).toHaveBeenCalledWith(null, "", "/issues/PAP-1"); expect(replaceStateSpy).toHaveBeenCalledWith(null, "", "/issues/PAP-1");
replaceStateSpy.mockRestore(); replaceStateSpy.mockRestore();
act(() => { flushAct(() => {
root.unmount(); root.unmount();
}); });
}); });
+26
View File
@@ -324,6 +324,32 @@ describe("buildIssueChatMessages", () => {
}); });
}); });
it("redacts deleted comment bodies while preserving tombstone metadata", () => {
const messages = buildIssueChatMessages({
comments: [
createComment({
body: "Sensitive deleted body",
deletedAt: new Date("2026-04-06T12:05:00.000Z"),
deletedByType: "user",
deletedByUserId: "user-1",
}),
],
timelineEvents: [],
linkedRuns: [],
liveRuns: [],
currentUserId: "user-1",
userLabelMap: new Map([["user-1", "Dotta"]]),
});
expect(messages[0]?.content).toEqual([{ type: "text", text: "" }]);
expect(messages[0]?.metadata.custom).toMatchObject({
deletedAt: "2026-04-06T12:05:00.000Z",
deletedByType: "user",
deletedByUserId: "user-1",
});
expect(JSON.stringify(messages[0])).not.toContain("Sensitive deleted body");
});
it("prefers derived agent attribution when a board-authored comment is proven to come from a run", () => { it("prefers derived agent attribution when a board-authored comment is proven to come from a run", () => {
const agentMap = new Map<string, Agent>([["agent-1", createAgent("agent-1", "Claude")]]); const agentMap = new Map<string, Agent>([["agent-1", createAgent("agent-1", "Claude")]]);
const messages = buildIssueChatMessages({ const messages = buildIssueChatMessages({