admonition.test.tsx111 lines · main
1import { render, screen, within } from '@testing-library/react'
2import { describe, expect, it } from 'vitest'
3
4import { Admonition, type AdmonitionProps } from './admonition'
5
6const stringDescriptionProps = {
7 description: 'Description-only copy.',
8} satisfies AdmonitionProps
9
10void stringDescriptionProps
11
12describe('Admonition', () => {
13 it('renders description-only content', () => {
14 render(<Admonition type="default" description="Changes can take a few minutes to apply." />)
15
16 expect(screen.getByRole('alert')).toHaveTextContent('Changes can take a few minutes to apply.')
17 })
18
19 it('renders children-only rich MDX-like content', () => {
20 render(
21 <Admonition type="note">
22 <p>
23 This is a Postgres{' '}
24 <a href="/docs/guides/database/postgres/row-level-security">SECURITY DEFINER</a> function.
25 </p>
26 <ul>
27 <li>Keep privileges scoped.</li>
28 </ul>
29 </Admonition>
30 )
31
32 const alert = screen.getByRole('alert')
33 expect(within(alert).getByText('SECURITY DEFINER')).toHaveAttribute(
34 'href',
35 '/docs/guides/database/postgres/row-level-security'
36 )
37 expect(within(alert).getByText('Keep privileges scoped.')).toBeVisible()
38 })
39
40 it('renders title and description together', () => {
41 render(
42 <Admonition
43 type="warning"
44 title="Manual approval required"
45 description="Review the pending changes before continuing."
46 />
47 )
48
49 const alert = screen.getByRole('alert')
50 expect(alert).toHaveTextContent('Manual approval required')
51 expect(alert).toHaveTextContent('Review the pending changes before continuing.')
52 })
53
54 it('renders title and children together', () => {
55 render(
56 <Admonition type="caution" title="Security definer function">
57 <p>Review ownership before exposing this function.</p>
58 </Admonition>
59 )
60
61 const alert = screen.getByRole('alert')
62 expect(alert).toHaveTextContent('Security definer function')
63 expect(alert).toHaveTextContent('Review ownership before exposing this function.')
64 })
65
66 it('renders success state with success styling', () => {
67 render(
68 <Admonition
69 type="success"
70 title="Connection confirmed"
71 description="You can now close this tab."
72 />
73 )
74
75 const alert = screen.getByRole('alert')
76 expect(alert).toHaveTextContent('Connection confirmed')
77 expect(alert).toHaveTextContent('You can now close this tab.')
78 expect(alert).toHaveClass('bg-brand-400/15')
79 expect(alert).toHaveClass('border-brand-400')
80 expect(alert.querySelector('svg path')?.getAttribute('d')).toContain('M10.5 19.5')
81 })
82
83 it('does not render the destructive icon when showIcon is false', () => {
84 render(
85 <Admonition
86 type="destructive"
87 showIcon={false}
88 title="Deletion blocked"
89 description="Resolve dependent resources before retrying."
90 />
91 )
92
93 const alert = screen.getByRole('alert')
94 expect(alert).toHaveTextContent('Deletion blocked')
95 expect(alert.querySelector('svg')).not.toBeInTheDocument()
96 })
97
98 it('prefers title over legacy label when both are provided', () => {
99 render(
100 <Admonition
101 type="note"
102 label="Legacy heading"
103 title="Preferred heading"
104 description="Body copy."
105 />
106 )
107
108 expect(screen.getByText('Preferred heading')).toBeVisible()
109 expect(screen.queryByText('Legacy heading')).not.toBeInTheDocument()
110 })
111})