MarkdownRenderer.test.tsx (3345B)
1 import { describe, it, expect, vi, beforeEach } from "vitest"; 2 import { render, screen } from "@testing-library/react"; 3 import { MarkdownRenderer } from "./MarkdownRenderer"; 4 5 beforeEach(() => { 6 Element.prototype.scrollIntoView = vi.fn(); 7 }); 8 9 describe("MarkdownRenderer", () => { 10 it("renders plain text", () => { 11 render(<MarkdownRenderer content="Hello world" />); 12 expect(screen.getByText("Hello world")).toBeInTheDocument(); 13 }); 14 15 it("renders inline code", () => { 16 render(<MarkdownRenderer content="Use `code` here" />); 17 expect(screen.getByText("code")).toBeInTheDocument(); 18 }); 19 20 it("renders code blocks with language", () => { 21 const { container } = render( 22 <MarkdownRenderer content={'```javascript\nconst x = 1;\n```'} />, 23 ); 24 // Syntax highlighter wraps in a code element with class 25 expect(container.querySelector("code.language-javascript")).toBeInTheDocument(); 26 }); 27 28 it("renders code blocks without language", () => { 29 const { container } = render( 30 <MarkdownRenderer content={'```\nsome code\n```'} />, 31 ); 32 expect(container.querySelector("pre")).toBeInTheDocument(); 33 }); 34 35 it("renders links with target blank", () => { 36 render(<MarkdownRenderer content="[click here](https://example.com)" />); 37 const link = screen.getByText("click here"); 38 expect(link).toHaveAttribute("href", "https://example.com"); 39 expect(link).toHaveAttribute("target", "_blank"); 40 expect(link).toHaveAttribute("rel", "noopener noreferrer"); 41 }); 42 43 it("renders lists", () => { 44 render(<MarkdownRenderer content={"- item 1\n- item 2"} />); 45 expect(screen.getByText("item 1")).toBeInTheDocument(); 46 expect(screen.getByText("item 2")).toBeInTheDocument(); 47 }); 48 49 it("renders ordered lists", () => { 50 render(<MarkdownRenderer content={"1. first\n2. second"} />); 51 expect(screen.getByText("first")).toBeInTheDocument(); 52 expect(screen.getByText("second")).toBeInTheDocument(); 53 }); 54 55 it("renders blockquotes", () => { 56 render(<MarkdownRenderer content={"> Important note"} />); 57 expect(screen.getByText("Important note")).toBeInTheDocument(); 58 }); 59 60 it("renders headings h1, h2, h3", () => { 61 render(<MarkdownRenderer content={"# H1\n## H2\n### H3"} />); 62 expect(screen.getByText("H1")).toBeInTheDocument(); 63 expect(screen.getByText("H2")).toBeInTheDocument(); 64 expect(screen.getByText("H3")).toBeInTheDocument(); 65 }); 66 67 it("renders bold and italic", () => { 68 render(<MarkdownRenderer content={"**bold** and *italic*"} />); 69 expect(screen.getByText("bold")).toBeInTheDocument(); 70 expect(screen.getByText("italic")).toBeInTheDocument(); 71 }); 72 73 it("renders paragraph breaks", () => { 74 render(<MarkdownRenderer content={"First paragraph\n\nSecond paragraph"} />); 75 expect(screen.getByText("First paragraph")).toBeInTheDocument(); 76 expect(screen.getByText("Second paragraph")).toBeInTheDocument(); 77 }); 78 79 it("renders empty content", () => { 80 const { container } = render(<MarkdownRenderer content="" />); 81 expect(container.querySelector(".prose")).toBeInTheDocument(); 82 }); 83 84 it("renders horizontal rules", () => { 85 render(<MarkdownRenderer content={"before\n\n---\n\nafter"} />); 86 expect(screen.getByText("before")).toBeInTheDocument(); 87 expect(screen.getByText("after")).toBeInTheDocument(); 88 }); 89 });