Barazo default frontend
barazo.forum
1/**
2 * Tests for MarkdownContent component.
3 */
4
5import { describe, it, expect } from 'vitest'
6import { render, screen } from '@testing-library/react'
7import { axe } from 'vitest-axe'
8import { MarkdownContent } from './markdown-content'
9
10describe('MarkdownContent', () => {
11 it('renders plain text', () => {
12 render(<MarkdownContent content="Hello world" />)
13 expect(screen.getByText('Hello world')).toBeInTheDocument()
14 })
15
16 it('renders bold text', () => {
17 const { container } = render(<MarkdownContent content="This is **bold** text" />)
18 const strong = container.querySelector('strong')
19 expect(strong).toBeInTheDocument()
20 expect(strong).toHaveTextContent('bold')
21 })
22
23 it('renders italic text', () => {
24 const { container } = render(<MarkdownContent content="This is *italic* text" />)
25 const em = container.querySelector('em')
26 expect(em).toBeInTheDocument()
27 expect(em).toHaveTextContent('italic')
28 })
29
30 it('renders links with target and rel attributes', () => {
31 render(<MarkdownContent content="Visit [Example](https://example.com)" />)
32 const link = screen.getByRole('link', { name: 'Example' })
33 expect(link).toHaveAttribute('href', 'https://example.com')
34 expect(link).toHaveAttribute('rel', expect.stringContaining('noopener'))
35 })
36
37 it('renders code blocks', () => {
38 const { container } = render(<MarkdownContent content={'```\nconst x = 1;\n```'} />)
39 const code = container.querySelector('code')
40 expect(code).toBeInTheDocument()
41 expect(code).toHaveTextContent('const x = 1;')
42 })
43
44 it('renders inline code', () => {
45 const { container } = render(<MarkdownContent content="Use `npm install` to install" />)
46 const code = container.querySelector('code')
47 expect(code).toBeInTheDocument()
48 expect(code).toHaveTextContent('npm install')
49 })
50
51 it('renders unordered lists', () => {
52 const { container } = render(<MarkdownContent content={'- Item 1\n- Item 2\n- Item 3'} />)
53 const list = container.querySelector('ul')
54 expect(list).toBeInTheDocument()
55 const items = container.querySelectorAll('li')
56 expect(items.length).toBe(3)
57 })
58
59 it('strips dangerous HTML (XSS prevention)', () => {
60 const { container } = render(
61 <MarkdownContent content='<script>alert("xss")</script><p>Safe content</p>' />
62 )
63 expect(container.querySelector('script')).not.toBeInTheDocument()
64 expect(screen.getByText('Safe content')).toBeInTheDocument()
65 })
66
67 it('strips event handler attributes', () => {
68 const { container } = render(
69 <MarkdownContent content='<img src="x" onerror="alert(1)"><p>Safe</p>' />
70 )
71 const img = container.querySelector('img')
72 if (img) {
73 expect(img.getAttribute('onerror')).toBeNull()
74 }
75 })
76
77 it('applies prose styling class', () => {
78 const { container } = render(<MarkdownContent content="Hello" />)
79 const wrapper = container.firstChild as HTMLElement
80 expect(wrapper.className).toContain('prose')
81 })
82
83 it('passes axe accessibility check', async () => {
84 const { container } = render(
85 <MarkdownContent
86 content={
87 '## Heading\n\nA paragraph with **bold** and a [link](https://example.com).\n\n- Item 1\n- Item 2'
88 }
89 />
90 )
91 const results = await axe(container)
92 expect(results).toHaveNoViolations()
93 })
94})