Files
oh-my-pi/packages/collab-web/test/transcript.test.tsx
T
roboomp 8480a84b3c fix(collab-web): preserve active transcript args
- Render deduped active tool cards with the execution args carried by ActiveTool.
- Covered differing raw assistant args and effective active args in the transcript regression test.

Fixes #4948
2026-07-09 17:04:32 +00:00

115 lines
3.0 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import type { AssistantMessage, SessionEntry } from "@oh-my-pi/pi-wire";
import { renderToStaticMarkup } from "react-dom/server";
import "./transcript-dom-shim";
import { Transcript } from "../src/components/transcript/Transcript";
import type { ActiveTool } from "../src/lib/client";
const TOOL_CALL_ID = "call-running-tool";
const TOOL_NAME = "probe_tool";
const RAW_ASSISTANT_TARGET = "stale-raw-assistant-target";
const ACTIVE_TOOL_TARGET = "effective-active-tool-target";
function assistantUsage(): AssistantMessage["usage"] {
return { input: 1, output: 2, cacheRead: 0, cacheWrite: 0, totalTokens: 3, cost: { total: 0 } };
}
function committedAssistantToolCall(): SessionEntry {
return {
type: "message",
id: "assistant-entry-1",
parentId: null,
timestamp: "2026-07-09T00:00:00Z",
message: {
role: "assistant",
content: [
{ type: "text", text: "I will run the tool." },
{
type: "toolCall",
id: TOOL_CALL_ID,
name: TOOL_NAME,
arguments: { target: RAW_ASSISTANT_TARGET },
intent: "Inspect fixture input",
},
],
model: "test/model",
usage: assistantUsage(),
stopReason: "stop",
timestamp: 1,
},
};
}
function activeTool(): ActiveTool {
return {
toolCallId: TOOL_CALL_ID,
toolName: TOOL_NAME,
args: { target: ACTIVE_TOOL_TARGET },
intent: "Inspect fixture input",
startedAt: 1,
};
}
function renderTranscript(props: {
entries?: readonly SessionEntry[];
activeTools?: ReadonlyMap<string, ActiveTool>;
working: boolean;
}): string {
return renderToStaticMarkup(
<Transcript
entries={props.entries ?? []}
stream={null}
streamDone={true}
activeTools={props.activeTools ?? new Map()}
working={props.working}
/>,
);
}
function countElements(html: string, selector: string): number {
let count = 0;
new HTMLRewriter()
.on(selector, {
element() {
count++;
},
})
.transform(html);
return count;
}
function countOccurrences(text: string, needle: string): number {
let count = 0;
let start = 0;
while (true) {
const index = text.indexOf(needle, start);
if (index === -1) return count;
count++;
start = index + needle.length;
}
}
describe("Transcript live tool rendering", () => {
it("renders one running card for a committed tool call using active args without the working shimmer", () => {
const html = renderTranscript({
entries: [committedAssistantToolCall()],
activeTools: new Map([[TOOL_CALL_ID, activeTool()]]),
working: true,
});
expect(countElements(html, ".tv-card")).toBe(1);
expect(countElements(html, '[aria-label="running"]')).toBe(1);
expect(countOccurrences(html, TOOL_NAME)).toBe(1);
expect(html).not.toContain("thinking…");
expect(html).toContain(ACTIVE_TOOL_TARGET);
expect(html).not.toContain(RAW_ASSISTANT_TARGET);
});
it("keeps the working shimmer when no tool is active", () => {
const html = renderTranscript({ working: true, activeTools: new Map() });
expect(html).toContain("thinking…");
});
});