Files
cobble/src/utils/conversation-markdown.test.ts
T
tbenandClaude Opus 5.5 84f8c0cac8 Let users copy the current chat session as markdown
The conversation header menu gets a Copy chat row that puts the active
session on the clipboard as one markdown document: a summary, then each
message under its author and time, with quotes, attachments and
reactions. Bot and workspace refs read as names, message headings drop
below the message headings and code blocks stay untouched. The clipboard
write starts on the click with a pending ClipboardItem so Safari allows
it after the fetch.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 11:49:46 +01:00

86 lines
2.6 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import type { ConversationExport } from "@/src/types";
import conversationMarkdown from "./conversation-markdown";
const format_time = (time: number) => `t${time}`;
const conversation: ConversationExport = {
bot_name: "Ada",
workspace_name: "Launch",
user_name: "Ben",
session: { id: 1, title: "Kickoff", created_at: 10 },
messages: [
{ id: 1, session_id: 1, author: "user", text: "Hi [bot:3]", created_at: 11 },
{
id: 2,
session_id: 1,
author: "bot",
text: "## Plan\n\nDone.",
created_at: 12,
attachments: [{ id: 5, name: "plan.pdf", media_type: "document", url: "" }],
reactions: [{ emoji: "👍", count: 2, mine: true }],
},
{
id: 3,
session_id: 1,
author: "user",
text: "Thanks",
created_at: 13,
reply_to: { id: 2, author: "bot", text: "## Plan\n\nDone." },
},
],
ref_names: { bots: { 3: "Ada" }, workspaces: {} },
};
describe("conversationMarkdown", () => {
test("lays out the session's messages", () => {
expect(conversationMarkdown({ conversation, now: 100, format_time })).toBe(
[
"# Kickoff",
"",
"- **Bot:** Ada",
"- **Workspace:** Launch",
"- **Participants:** Ben, Ada",
"- **Started:** t10",
"- **Messages:** 3",
"- **Copied:** t100",
"",
"---",
"",
"## Ben · t11",
"",
"Hi @Ada",
"",
"## Ada · t12",
"",
"#### Plan",
"",
"Done.",
"",
"*Attached: plan.pdf*",
"",
"*Reactions: 👍 2*",
"",
"## Ben · t13",
"",
"> Replying to Ada: Plan Done.",
"",
"Thanks",
"",
].join("\n"),
);
});
test("titles an untitled or empty session after the bot", () => {
const markdown = conversationMarkdown({
conversation: { ...conversation, session: null, messages: [] },
now: 1,
format_time,
});
expect(markdown).toStartWith("# Chat with Ada\n");
expect(markdown).toContain("*No messages yet.*");
expect(markdown).not.toContain("**Started:**");
});
});