/** * @file artifactView.test.ts * @description What counts as an artifact and how it is shown: kinds by * name, a React file only when written whole, a file's versions rebuilt from * the conversation's Write/Edit/MultiEdit inputs (a failed call skipped, an * edit to unseen text unknown), CSV rows, and the sandboxed documents. * @author Nguyễn Ngọc Trí Vĩ */ import { describe, expect, it } from "vitest"; import { artifactDocument, artifactKind, artifactVersions, frameSandbox, isArtifact, parseCsv, } from "../artifactView"; import type { TranscriptMessage } from "../types"; const use = (id: string, name: string, input: Record): TranscriptMessage => ({ type: "assistant", timestamp: `2026-10-21T00:00:0${id}.000Z`, content: [{ type: "tool_use", id, name, input } as TranscriptMessage["content"][number]], }); const result = (id: string, isError = false): TranscriptMessage => ({ type: "user", sender: "tool", timestamp: null, content: [ { type: "tool_result", id, output: "", is_error: isError, } as TranscriptMessage["content"][number], ], }); describe("artifactView", () => { it("knows an artifact by its name", () => { expect(artifactKind("/a/page.HTML")).toBe("html"); expect(artifactKind("d.mmd")).toBe("mermaid"); expect(artifactKind("App.tsx")).toBe("react"); expect(artifactKind("x.go")).toBe("code"); expect(isArtifact("report.md", false)).toBe(true); expect(isArtifact("App.tsx", false)).toBe(false); expect(isArtifact("App.tsx", true)).toBe(true); expect(isArtifact("server.js", true)).toBe(false); }); it("rebuilds a file's versions from Write, Edit and MultiEdit", () => { const msgs = [ use("1", "Write", { file_path: "/w/a.md", content: "# A\nold line\n" }), result("1"), use("2", "Edit", { file_path: "/w/a.md", old_string: "old", new_string: "new" }), result("2"), use("3", "Edit", { file_path: "/w/a.md", old_string: "missing", new_string: "x" }), result("3", true), use("4", "MultiEdit", { file_path: "/w/a.md", edits: [{ old_string: "# A", new_string: "# B" }], }), result("4"), use("5", "Write", { file_path: "/w/other.md", content: "no" }), ]; const v = artifactVersions(msgs, "/w/a.md"); expect(v.map((x) => x.content)).toEqual([ "# A\nold line\n", "# A\nnew line\n", "# B\nnew line\n", ]); }); it("says an edit to text it never saw is of unknown content", () => { const v = artifactVersions( [use("1", "Edit", { file_path: "a.md", old_string: "a", new_string: "b" })], "a.md" ); expect(v).toHaveLength(1); expect(v[0]!.content).toBeNull(); }); it("reads CSV with quotes and newlines inside them", () => { expect(parseCsv('a,b\n"x, y","say ""hi""\nthere"\n')).toEqual([ ["a", "b"], ["x, y", 'say "hi"\nthere'], ]); }); it("builds sandboxed documents that keep the source inert inside a script", () => { const doc = artifactDocument("react", "export default () =>

ab

", false)!; expect(doc).toContain("babel"); expect(doc).not.toContain("ab"); expect(artifactDocument("mermaid", "graph TD; A-->B", true)).toContain( "A-->B<img>" ); expect(artifactDocument("code", "x", false)).toBeNull(); expect(frameSandbox("svg")).toBe(""); expect(frameSandbox("html")).not.toContain("allow-same-origin"); }); });