750d74a2af
- omp-share.js: an admin's switch (S3) runs omp's own auth broker + gateway as the host on loopback; a member's omp pane reaches it as a scoped client keyed by its pane token (clients file = live omp panes only), runs on --model agenthub/<model>, never holds a credential. - omp catalog: --allow-home, so a workspace at the account's home keeps its sessions there (they were recorded under a temp dir and dropped). - Settings → Appearance → Open Markdown as: Preview (default) or Raw, for Files/Changes, the config viewer and a chat's file panel. - First-login password change and password rules, avatar URLs, Artifacts "Mine" includes installed shared skills/plugins, a member's own hook pages.
87 lines
3.6 KiB
TypeScript
87 lines
3.6 KiB
TypeScript
/**
|
|
* @file MarkdownPreview.test.tsx
|
|
* @description The markdown preview: GFM renders (headings, tables, task
|
|
* lists), raw HTML stays text, links open in a new tab, frontmatter is a
|
|
* code block; and the config FileViewer offers Raw / Preview only for a
|
|
* markdown file.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
|
|
import { render, screen } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
import { MarkdownPreview, isMarkdown } from "../MarkdownPreview";
|
|
import { FileViewer } from "../config/FileViewer";
|
|
|
|
describe("MarkdownPreview", () => {
|
|
it("renders GFM: headings, tables and task lists", () => {
|
|
render(
|
|
<MarkdownPreview
|
|
text={"# Title\n\n| a | b |\n|---|---|\n| 1 | 2 |\n\n- [x] done\n- [ ] todo\n"}
|
|
/>
|
|
);
|
|
expect(screen.getByRole("heading", { level: 1, name: "Title" })).toBeInTheDocument();
|
|
expect(screen.getByRole("table")).toBeInTheDocument();
|
|
expect(screen.getAllByRole("checkbox")).toHaveLength(2);
|
|
});
|
|
|
|
it("never runs raw HTML and opens links in a new tab", () => {
|
|
const { container } = render(
|
|
<MarkdownPreview
|
|
text={'<script>alert(1)</script><img src=x onerror="alert(1)">\n\n[x](https://a.example)'}
|
|
/>
|
|
);
|
|
expect(container.querySelector("script")).toBeNull();
|
|
expect(container.querySelector("img")).toBeNull();
|
|
const link = screen.getByRole("link", { name: "x" });
|
|
expect(link).toHaveAttribute("target", "_blank");
|
|
expect(link).toHaveAttribute("rel", "noreferrer noopener");
|
|
});
|
|
|
|
it("shows frontmatter as a block, not as a heading", () => {
|
|
const { container } = render(
|
|
<MarkdownPreview text={"---\nname: demo\ndescription: d\n---\n\nBody text\n"} />
|
|
);
|
|
expect(container.querySelector(".md-frontmatter")).toHaveTextContent("name: demo");
|
|
expect(screen.queryByRole("heading")).toBeNull();
|
|
expect(screen.getByText("Body text")).toBeInTheDocument();
|
|
});
|
|
|
|
it("knows a markdown path", () => {
|
|
expect(isMarkdown("/a/SKILL.md")).toBe(true);
|
|
expect(isMarkdown("README.markdown")).toBe(true);
|
|
expect(isMarkdown("config.toml")).toBe(false);
|
|
expect(isMarkdown(null)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("FileViewer — markdown preview", () => {
|
|
const data = { text: "# Hello\n", truncated: false } as never;
|
|
|
|
it("opens a markdown file rendered, and switches it to raw and back", async () => {
|
|
render(<FileViewer state={{ path: "/x/CLAUDE.md", data, error: null }} onClose={vi.fn()} />);
|
|
expect(screen.getByRole("heading", { name: "Hello" })).toBeInTheDocument();
|
|
await userEvent.click(screen.getByRole("button", { name: "Raw" }));
|
|
expect(screen.queryByTestId("markdown-preview")).toBeNull();
|
|
expect(screen.getByText("# Hello")).toBeInTheDocument();
|
|
await userEvent.click(screen.getByRole("button", { name: "Preview" }));
|
|
expect(screen.getByRole("heading", { name: "Hello" })).toBeInTheDocument();
|
|
});
|
|
|
|
it("opens it as source when Settings → Appearance says Raw", () => {
|
|
window.localStorage.setItem("agenthub.markdown.view", "raw");
|
|
try {
|
|
render(<FileViewer state={{ path: "/x/CLAUDE.md", data, error: null }} onClose={vi.fn()} />);
|
|
expect(screen.queryByTestId("markdown-preview")).toBeNull();
|
|
expect(screen.getByText("# Hello")).toBeInTheDocument();
|
|
} finally {
|
|
window.localStorage.removeItem("agenthub.markdown.view");
|
|
}
|
|
});
|
|
|
|
it("offers no preview for another file type", () => {
|
|
render(<FileViewer state={{ path: "/x/config.toml", data, error: null }} onClose={vi.fn()} />);
|
|
expect(screen.queryByRole("button", { name: "Preview" })).toBeNull();
|
|
});
|
|
});
|