Skip to content
Source
Sign inSign up

markdownDetails.test.ts

80 lines3.2 KB

1import { describe, expect, it } from "vite-plus/test";
2​
3import { splitMarkdownDetails } from "./markdownDetails";
4​
5describe("splitMarkdownDetails", () => {
6 // regression: #28059 mobile chat showed every <details> fold open
7 it("splits a top-level fold into its summary and hidden body", () => {
8 const markdown =
9 "Short answer.\n\n<details>\n<summary>Long details</summary>\n\nA long paragraph.\n\n</details>\n\nAfter.";
10 expect(splitMarkdownDetails(markdown)).toEqual([
11 { kind: "markdown", markdown: "Short answer.\n\n", sourceOffset: 0 },
12 {
13 kind: "details",
14 summary: "Long details",
15 body: "\n\nA long paragraph.\n\n",
16 open: false,
17 sourceOffset: 15,
18 },
19 { kind: "markdown", markdown: "\n\nAfter.", sourceOffset: 87 },
20 ]);
21 });
22​
23 it("keeps nested folds in the body and honours the open attribute", () => {
24 const markdown =
25 "<details open>\n<summary>Outer &amp; <code>more</code></summary>\n\n<details>\n<summary>Inner</summary>\n\nx\n\n</details>\n\n</details>";
26 const [fold] = splitMarkdownDetails(markdown);
27 expect(fold).toMatchObject({ kind: "details", summary: "Outer & more", open: true });
28 expect(fold?.kind === "details" && splitMarkdownDetails(fold.body)).toMatchObject([
29 { kind: "markdown" },
30 { kind: "details", summary: "Inner", body: "\n\nx\n\n" },
31 { kind: "markdown" },
32 ]);
33 });
34​
35 it("leaves folds in code and inline tags as markdown", () => {
36 for (const markdown of [
37 "```html\n<details>\n<summary>Code</summary>\n</details>\n```",
38 "Use `<details>` for folds.",
39 "Text <details><summary>inline</summary>body</details> more",
40 "<!-- <details> -->\n\nVisible answer.",
41 ]) {
42 expect(splitMarkdownDetails(markdown)).toEqual([
43 { kind: "markdown", markdown, sourceOffset: 0 },
44 ]);
45 }
46 });
47​
48 it("ignores a closing tag inside a code example in the fold", () => {
49 const markdown =
50 "<details>\n<summary>Example</summary>\n```html\n</details>\n```\n</details>\n\nAfter.";
51 expect(splitMarkdownDetails(markdown)).toMatchObject([
52 { kind: "details", summary: "Example", body: "\n```html\n</details>\n```\n" },
53 { kind: "markdown", markdown: "\n\nAfter." },
54 ]);
55 });
56​
57 it("closes a fold at a closing tag that ends a paragraph", () => {
58 expect(
59 splitMarkdownDetails("<details>\n<summary>Plan</summary>\n\nDone </details>\n\nNext step"),
60 ).toMatchObject([
61 { kind: "details", summary: "Plan", body: "\n\nDone " },
62 { kind: "markdown", markdown: "\n\nNext step" },
63 ]);
64 });
65​
66 it("folds the rest of a reply whose closing tag has not streamed yet", () => {
67 expect(splitMarkdownDetails("<details>\n<summary>Plan</summary>\n\nStep one")).toEqual([
68 { kind: "details", summary: "Plan", body: "\n\nStep one", open: false, sourceOffset: 0 },
69 ]);
70 expect(
71 splitMarkdownDetails("<details>\n<summary>Plan</summary>\n\n```html\n</details>"),
72 ).toMatchObject([{ kind: "details", body: "\n\n```html\n</details>" }]);
73 });
74​
75 it("reads open only as an attribute name", () => {
76 expect(
77 splitMarkdownDetails('<details title="is open">\n<summary>Plan</summary>\n</details>'),
78 ).toMatchObject([{ kind: "details", open: false }]);
79 });
80});