@moontra/moonui 2.0.8 → 2.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -2
- package/src/__tests__/use-intersection-observer.test.tsx +216 -0
- package/src/__tests__/use-local-storage.test.tsx +174 -0
- package/src/__tests__/use-pro-access.test.tsx +183 -0
- package/src/components/ui/__tests__/accordion.test.tsx +571 -0
- package/src/components/ui/__tests__/alert.test.tsx +484 -0
- package/src/components/ui/__tests__/aspect-ratio.test.tsx +492 -0
- package/src/components/ui/__tests__/avatar.test.tsx +382 -0
- package/src/components/ui/__tests__/badge.test.tsx +364 -0
- package/src/components/ui/__tests__/breadcrumb.test.tsx +687 -0
- package/src/components/ui/__tests__/button.test.tsx +91 -0
- package/src/components/ui/__tests__/card.test.tsx +104 -0
- package/src/components/ui/__tests__/checkbox.test.tsx +591 -0
- package/src/components/ui/__tests__/collapsible.test.tsx +592 -0
- package/src/components/ui/__tests__/color-picker.test.tsx +365 -0
- package/src/components/ui/__tests__/command.test.tsx +677 -0
- package/src/components/ui/__tests__/data-table.test.tsx +256 -0
- package/src/components/ui/__tests__/date-picker.test.tsx +320 -0
- package/src/components/ui/__tests__/dialog.test.tsx +764 -0
- package/src/components/ui/__tests__/input.test.tsx +318 -0
- package/src/components/ui/__tests__/label.test.tsx +103 -0
- package/src/components/ui/__tests__/popover.test.tsx +637 -0
- package/src/components/ui/__tests__/progress.test.tsx +382 -0
- package/src/components/ui/__tests__/radio-group.test.tsx +555 -0
- package/src/components/ui/__tests__/select.test.tsx +705 -0
- package/src/components/ui/__tests__/skeleton.test.tsx +253 -0
- package/src/components/ui/__tests__/slider.test.tsx +493 -0
- package/src/components/ui/__tests__/switch.test.tsx +372 -0
- package/src/components/ui/__tests__/table.test.tsx +824 -0
- package/src/components/ui/__tests__/tabs.test.tsx +887 -0
- package/src/components/ui/__tests__/toast.test.tsx +458 -0
- package/src/components/ui/__tests__/tooltip.test.tsx +583 -0
- package/src/components/ui/accordion.tsx +63 -0
- package/src/components/ui/alert.tsx +130 -0
- package/src/components/ui/aspect-ratio.tsx +72 -0
- package/src/components/ui/avatar.tsx +135 -0
- package/src/components/ui/badge.tsx +225 -0
- package/src/components/ui/breadcrumb.tsx +207 -0
- package/src/components/ui/button.stories.tsx +162 -0
- package/src/components/ui/button.tsx +221 -0
- package/src/components/ui/calendar.tsx +262 -0
- package/src/components/ui/card.stories.tsx +208 -0
- package/src/components/ui/card.tsx +141 -0
- package/src/components/ui/checkbox.tsx +256 -0
- package/src/components/ui/collapsible.tsx +129 -0
- package/src/components/ui/color-picker.tsx +664 -0
- package/src/components/ui/command.tsx +218 -0
- package/src/components/ui/data-table.stories.tsx +509 -0
- package/src/components/ui/data-table.tsx +623 -0
- package/src/components/ui/date-picker.stories.tsx +321 -0
- package/src/components/ui/date-picker.tsx +603 -0
- package/src/components/ui/dialog.tsx +332 -0
- package/src/components/ui/dropdown-menu.tsx +200 -0
- package/src/components/ui/file-upload.tsx +400 -0
- package/src/components/ui/github-stars.tsx +201 -0
- package/src/components/ui/index.ts +12 -0
- package/src/components/ui/input.stories.tsx +255 -0
- package/src/components/ui/input.tsx +219 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/locked-component.tsx +215 -0
- package/src/components/ui/moon-logo.tsx +97 -0
- package/src/components/ui/pagination.tsx +116 -0
- package/src/components/ui/popover.tsx +183 -0
- package/src/components/ui/progress.tsx +182 -0
- package/src/components/ui/radio-group.tsx +243 -0
- package/src/components/ui/select.tsx +273 -0
- package/src/components/ui/separator.tsx +140 -0
- package/src/components/ui/simple-editor.tsx +652 -0
- package/src/components/ui/skeleton.tsx +351 -0
- package/src/components/ui/slider.tsx +351 -0
- package/src/components/ui/switch.tsx +83 -0
- package/src/components/ui/table.tsx +322 -0
- package/src/components/ui/tabs.tsx +195 -0
- package/src/components/ui/textarea.tsx +46 -0
- package/src/components/ui/toast.tsx +313 -0
- package/src/components/ui/toggle.tsx +47 -0
- package/src/components/ui/tooltip.tsx +152 -0
- package/src/docs/theme-system.md +1194 -0
- package/src/index.tsx +39 -0
- package/src/lib/micro-interactions.ts +255 -0
- package/src/lib/theme.tsx +398 -0
- package/src/lib/utils.ts +69 -0
- package/src/styles/design-system.css +365 -0
- package/src/styles/index.css +4 -0
- package/src/styles/tailwind.css +6 -0
- package/src/styles/tokens.css +453 -0
- package/src/use-intersection-observer.tsx +154 -0
- package/src/use-local-storage.tsx +71 -0
- package/src/use-paddle.ts +138 -0
- package/src/use-performance-optimizer.ts +379 -0
- package/src/use-pro-access.ts +141 -0
- package/src/use-scroll-animation.ts +221 -0
- package/src/use-subscription.ts +37 -0
- package/src/use-toast.ts +32 -0
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react'
|
|
3
|
+
import '@testing-library/jest-dom'
|
|
4
|
+
import { Alert, AlertTitle, AlertDescription } from '../alert'
|
|
5
|
+
|
|
6
|
+
describe('Alert Components', () => {
|
|
7
|
+
describe('Alert Component', () => {
|
|
8
|
+
describe('Basic Rendering', () => {
|
|
9
|
+
it('renders correctly with default props', () => {
|
|
10
|
+
render(<Alert data-testid="alert">Test alert</Alert>)
|
|
11
|
+
const alert = screen.getByTestId('alert')
|
|
12
|
+
expect(alert).toBeInTheDocument()
|
|
13
|
+
expect(alert).toHaveAttribute('role', 'alert')
|
|
14
|
+
expect(alert).toHaveTextContent('Test alert')
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('applies custom className', () => {
|
|
18
|
+
render(<Alert className="custom-alert" data-testid="alert">Test</Alert>)
|
|
19
|
+
const alert = screen.getByTestId('alert')
|
|
20
|
+
expect(alert).toHaveClass('custom-alert')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('forwards ref correctly', () => {
|
|
24
|
+
const ref = React.createRef<HTMLDivElement>()
|
|
25
|
+
render(<Alert ref={ref} data-testid="alert">Test</Alert>)
|
|
26
|
+
expect(ref.current).toBeInstanceOf(HTMLDivElement)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('maintains displayName', () => {
|
|
30
|
+
expect(Alert.displayName).toBe('Alert')
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
describe('Variants', () => {
|
|
35
|
+
it('renders default variant correctly', () => {
|
|
36
|
+
render(<Alert variant="default" data-testid="alert">Test</Alert>)
|
|
37
|
+
const alert = screen.getByTestId('alert')
|
|
38
|
+
expect(alert).toHaveClass('bg-background')
|
|
39
|
+
expect(alert).toHaveClass('text-foreground')
|
|
40
|
+
expect(alert).toHaveClass('border-border')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('renders primary variant correctly', () => {
|
|
44
|
+
render(<Alert variant="primary" data-testid="alert">Test</Alert>)
|
|
45
|
+
const alert = screen.getByTestId('alert')
|
|
46
|
+
expect(alert).toHaveClass('bg-primary/10')
|
|
47
|
+
expect(alert).toHaveClass('text-primary')
|
|
48
|
+
expect(alert).toHaveClass('border-primary/30')
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('renders success variant correctly', () => {
|
|
52
|
+
render(<Alert variant="success" data-testid="alert">Test</Alert>)
|
|
53
|
+
const alert = screen.getByTestId('alert')
|
|
54
|
+
expect(alert).toHaveClass('bg-success/10')
|
|
55
|
+
expect(alert).toHaveClass('text-success')
|
|
56
|
+
expect(alert).toHaveClass('border-success/30')
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('renders warning variant correctly', () => {
|
|
60
|
+
render(<Alert variant="warning" data-testid="alert">Test</Alert>)
|
|
61
|
+
const alert = screen.getByTestId('alert')
|
|
62
|
+
expect(alert).toHaveClass('bg-warning/10')
|
|
63
|
+
expect(alert).toHaveClass('text-warning')
|
|
64
|
+
expect(alert).toHaveClass('border-warning/30')
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('renders error variant correctly', () => {
|
|
68
|
+
render(<Alert variant="error" data-testid="alert">Test</Alert>)
|
|
69
|
+
const alert = screen.getByTestId('alert')
|
|
70
|
+
expect(alert).toHaveClass('bg-destructive/10')
|
|
71
|
+
expect(alert).toHaveClass('text-destructive')
|
|
72
|
+
expect(alert).toHaveClass('border-destructive/30')
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('renders info variant correctly', () => {
|
|
76
|
+
render(<Alert variant="info" data-testid="alert">Test</Alert>)
|
|
77
|
+
const alert = screen.getByTestId('alert')
|
|
78
|
+
expect(alert).toHaveClass('bg-blue-500/10')
|
|
79
|
+
expect(alert).toHaveClass('text-blue-500')
|
|
80
|
+
expect(alert).toHaveClass('border-blue-500/30')
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('uses default variant as default', () => {
|
|
84
|
+
render(<Alert data-testid="alert">Test</Alert>)
|
|
85
|
+
const alert = screen.getByTestId('alert')
|
|
86
|
+
expect(alert).toHaveClass('bg-background')
|
|
87
|
+
expect(alert).toHaveClass('text-foreground')
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
describe('Sizes', () => {
|
|
92
|
+
it('renders sm size correctly', () => {
|
|
93
|
+
render(<Alert size="sm" data-testid="alert">Test</Alert>)
|
|
94
|
+
const alert = screen.getByTestId('alert')
|
|
95
|
+
expect(alert).toHaveClass('py-2')
|
|
96
|
+
expect(alert).toHaveClass('text-xs')
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it('renders default size correctly', () => {
|
|
100
|
+
render(<Alert size="default" data-testid="alert">Test</Alert>)
|
|
101
|
+
const alert = screen.getByTestId('alert')
|
|
102
|
+
expect(alert).toHaveClass('py-3')
|
|
103
|
+
expect(alert).toHaveClass('text-sm')
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('renders lg size correctly', () => {
|
|
107
|
+
render(<Alert size="lg" data-testid="alert">Test</Alert>)
|
|
108
|
+
const alert = screen.getByTestId('alert')
|
|
109
|
+
expect(alert).toHaveClass('py-4')
|
|
110
|
+
expect(alert).toHaveClass('text-base')
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('uses default size as default', () => {
|
|
114
|
+
render(<Alert data-testid="alert">Test</Alert>)
|
|
115
|
+
const alert = screen.getByTestId('alert')
|
|
116
|
+
expect(alert).toHaveClass('py-3')
|
|
117
|
+
expect(alert).toHaveClass('text-sm')
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
describe('Radius', () => {
|
|
122
|
+
it('renders none radius correctly', () => {
|
|
123
|
+
render(<Alert radius="none" data-testid="alert">Test</Alert>)
|
|
124
|
+
const alert = screen.getByTestId('alert')
|
|
125
|
+
expect(alert).toHaveClass('rounded-none')
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('renders sm radius correctly', () => {
|
|
129
|
+
render(<Alert radius="sm" data-testid="alert">Test</Alert>)
|
|
130
|
+
const alert = screen.getByTestId('alert')
|
|
131
|
+
expect(alert).toHaveClass('rounded-sm')
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
it('renders default radius correctly', () => {
|
|
135
|
+
render(<Alert radius="default" data-testid="alert">Test</Alert>)
|
|
136
|
+
const alert = screen.getByTestId('alert')
|
|
137
|
+
expect(alert).toHaveClass('rounded-md')
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('renders lg radius correctly', () => {
|
|
141
|
+
render(<Alert radius="lg" data-testid="alert">Test</Alert>)
|
|
142
|
+
const alert = screen.getByTestId('alert')
|
|
143
|
+
expect(alert).toHaveClass('rounded-lg')
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
it('renders full radius correctly', () => {
|
|
147
|
+
render(<Alert radius="full" data-testid="alert">Test</Alert>)
|
|
148
|
+
const alert = screen.getByTestId('alert')
|
|
149
|
+
expect(alert).toHaveClass('rounded-full')
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
it('uses default radius as default', () => {
|
|
153
|
+
render(<Alert data-testid="alert">Test</Alert>)
|
|
154
|
+
const alert = screen.getByTestId('alert')
|
|
155
|
+
expect(alert).toHaveClass('rounded-md')
|
|
156
|
+
})
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
describe('Icons', () => {
|
|
160
|
+
it('renders default icon for default variant', () => {
|
|
161
|
+
render(<Alert variant="default" data-testid="alert">Test</Alert>)
|
|
162
|
+
const alert = screen.getByTestId('alert')
|
|
163
|
+
const icon = alert.querySelector('svg')
|
|
164
|
+
expect(icon).toBeInTheDocument()
|
|
165
|
+
expect(icon).toHaveClass('h-5', 'w-5')
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
it('renders check icon for success variant', () => {
|
|
169
|
+
render(<Alert variant="success" data-testid="alert">Test</Alert>)
|
|
170
|
+
const alert = screen.getByTestId('alert')
|
|
171
|
+
const icon = alert.querySelector('svg')
|
|
172
|
+
expect(icon).toBeInTheDocument()
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
it('renders triangle icon for warning variant', () => {
|
|
176
|
+
render(<Alert variant="warning" data-testid="alert">Test</Alert>)
|
|
177
|
+
const alert = screen.getByTestId('alert')
|
|
178
|
+
const icon = alert.querySelector('svg')
|
|
179
|
+
expect(icon).toBeInTheDocument()
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
it('renders circle icon for error variant', () => {
|
|
183
|
+
render(<Alert variant="error" data-testid="alert">Test</Alert>)
|
|
184
|
+
const alert = screen.getByTestId('alert')
|
|
185
|
+
const icon = alert.querySelector('svg')
|
|
186
|
+
expect(icon).toBeInTheDocument()
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
it('renders info icon for info variant', () => {
|
|
190
|
+
render(<Alert variant="info" data-testid="alert">Test</Alert>)
|
|
191
|
+
const alert = screen.getByTestId('alert')
|
|
192
|
+
const icon = alert.querySelector('svg')
|
|
193
|
+
expect(icon).toBeInTheDocument()
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
it('hides icon when hideIcon is true', () => {
|
|
197
|
+
render(<Alert hideIcon data-testid="alert">Test</Alert>)
|
|
198
|
+
const alert = screen.getByTestId('alert')
|
|
199
|
+
const icon = alert.querySelector('svg')
|
|
200
|
+
expect(icon).not.toBeInTheDocument()
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
it('shows icon when hideIcon is false', () => {
|
|
204
|
+
render(<Alert hideIcon={false} data-testid="alert">Test</Alert>)
|
|
205
|
+
const alert = screen.getByTestId('alert')
|
|
206
|
+
const icon = alert.querySelector('svg')
|
|
207
|
+
expect(icon).toBeInTheDocument()
|
|
208
|
+
})
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
describe('Closable Functionality', () => {
|
|
212
|
+
it('does not render close button by default', () => {
|
|
213
|
+
render(<Alert data-testid="alert">Test</Alert>)
|
|
214
|
+
const alert = screen.getByTestId('alert')
|
|
215
|
+
const closeButton = alert.querySelector('button')
|
|
216
|
+
expect(closeButton).not.toBeInTheDocument()
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
it('renders close button when closable is true', () => {
|
|
220
|
+
const handleClose = jest.fn()
|
|
221
|
+
render(<Alert closable onClose={handleClose} data-testid="alert">Test</Alert>)
|
|
222
|
+
const alert = screen.getByTestId('alert')
|
|
223
|
+
const closeButton = alert.querySelector('button')
|
|
224
|
+
expect(closeButton).toBeInTheDocument()
|
|
225
|
+
expect(closeButton).toHaveAttribute('aria-label', 'Kapat')
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
it('does not render close button when closable is true but onClose is not provided', () => {
|
|
229
|
+
render(<Alert closable data-testid="alert">Test</Alert>)
|
|
230
|
+
const alert = screen.getByTestId('alert')
|
|
231
|
+
const closeButton = alert.querySelector('button')
|
|
232
|
+
expect(closeButton).not.toBeInTheDocument()
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
it('calls onClose when close button is clicked', () => {
|
|
236
|
+
const handleClose = jest.fn()
|
|
237
|
+
render(<Alert closable onClose={handleClose} data-testid="alert">Test</Alert>)
|
|
238
|
+
const alert = screen.getByTestId('alert')
|
|
239
|
+
const closeButton = alert.querySelector('button')
|
|
240
|
+
|
|
241
|
+
fireEvent.click(closeButton!)
|
|
242
|
+
expect(handleClose).toHaveBeenCalledTimes(1)
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
it('applies withClose styling when closable', () => {
|
|
246
|
+
const handleClose = jest.fn()
|
|
247
|
+
render(<Alert closable onClose={handleClose} data-testid="alert">Test</Alert>)
|
|
248
|
+
const alert = screen.getByTestId('alert')
|
|
249
|
+
expect(alert).toHaveClass('pr-10')
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
it('close button has correct styling', () => {
|
|
253
|
+
const handleClose = jest.fn()
|
|
254
|
+
render(<Alert closable onClose={handleClose} data-testid="alert">Test</Alert>)
|
|
255
|
+
const alert = screen.getByTestId('alert')
|
|
256
|
+
const closeButton = alert.querySelector('button')
|
|
257
|
+
|
|
258
|
+
expect(closeButton).toHaveClass('absolute')
|
|
259
|
+
expect(closeButton).toHaveClass('right-3')
|
|
260
|
+
expect(closeButton).toHaveClass('top-3')
|
|
261
|
+
expect(closeButton).toHaveClass('h-6')
|
|
262
|
+
expect(closeButton).toHaveClass('w-6')
|
|
263
|
+
})
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
describe('Accessibility', () => {
|
|
267
|
+
it('has correct role attribute', () => {
|
|
268
|
+
render(<Alert data-testid="alert">Test</Alert>)
|
|
269
|
+
const alert = screen.getByTestId('alert')
|
|
270
|
+
expect(alert).toHaveAttribute('role', 'alert')
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
it('supports custom ARIA attributes', () => {
|
|
274
|
+
render(<Alert aria-label="Custom alert" data-testid="alert">Test</Alert>)
|
|
275
|
+
const alert = screen.getByTestId('alert')
|
|
276
|
+
expect(alert).toHaveAttribute('aria-label', 'Custom alert')
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
it('close button has accessible label', () => {
|
|
280
|
+
const handleClose = jest.fn()
|
|
281
|
+
render(<Alert closable onClose={handleClose} data-testid="alert">Test</Alert>)
|
|
282
|
+
const alert = screen.getByTestId('alert')
|
|
283
|
+
const closeButton = alert.querySelector('button')
|
|
284
|
+
expect(closeButton).toHaveAttribute('aria-label', 'Kapat')
|
|
285
|
+
})
|
|
286
|
+
})
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
describe('AlertTitle Component', () => {
|
|
290
|
+
it('renders correctly with default props', () => {
|
|
291
|
+
render(<AlertTitle data-testid="alert-title">Alert Title</AlertTitle>)
|
|
292
|
+
const title = screen.getByTestId('alert-title')
|
|
293
|
+
expect(title).toBeInTheDocument()
|
|
294
|
+
expect(title.tagName).toBe('H5')
|
|
295
|
+
expect(title).toHaveTextContent('Alert Title')
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
it('applies custom className', () => {
|
|
299
|
+
render(<AlertTitle className="custom-title" data-testid="alert-title">Title</AlertTitle>)
|
|
300
|
+
const title = screen.getByTestId('alert-title')
|
|
301
|
+
expect(title).toHaveClass('custom-title')
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
it('has correct default styling', () => {
|
|
305
|
+
render(<AlertTitle data-testid="alert-title">Title</AlertTitle>)
|
|
306
|
+
const title = screen.getByTestId('alert-title')
|
|
307
|
+
expect(title).toHaveClass('font-semibold')
|
|
308
|
+
expect(title).toHaveClass('leading-tight')
|
|
309
|
+
expect(title).toHaveClass('tracking-tight')
|
|
310
|
+
expect(title).toHaveClass('mb-1')
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
it('forwards ref correctly', () => {
|
|
314
|
+
const ref = React.createRef<HTMLParagraphElement>()
|
|
315
|
+
render(<AlertTitle ref={ref} data-testid="alert-title">Title</AlertTitle>)
|
|
316
|
+
expect(ref.current).toBeInstanceOf(HTMLHeadingElement)
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
it('maintains displayName', () => {
|
|
320
|
+
expect(AlertTitle.displayName).toBe('AlertTitle')
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
it('passes through HTML attributes', () => {
|
|
324
|
+
render(<AlertTitle id="alert-title-1" data-testid="alert-title">Title</AlertTitle>)
|
|
325
|
+
const title = screen.getByTestId('alert-title')
|
|
326
|
+
expect(title).toHaveAttribute('id', 'alert-title-1')
|
|
327
|
+
})
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
describe('AlertDescription Component', () => {
|
|
331
|
+
it('renders correctly with default props', () => {
|
|
332
|
+
render(<AlertDescription data-testid="alert-description">Alert Description</AlertDescription>)
|
|
333
|
+
const description = screen.getByTestId('alert-description')
|
|
334
|
+
expect(description).toBeInTheDocument()
|
|
335
|
+
expect(description.tagName).toBe('DIV')
|
|
336
|
+
expect(description).toHaveTextContent('Alert Description')
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
it('applies custom className', () => {
|
|
340
|
+
render(<AlertDescription className="custom-description" data-testid="alert-description">Description</AlertDescription>)
|
|
341
|
+
const description = screen.getByTestId('alert-description')
|
|
342
|
+
expect(description).toHaveClass('custom-description')
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
it('has correct default styling', () => {
|
|
346
|
+
render(<AlertDescription data-testid="alert-description">Description</AlertDescription>)
|
|
347
|
+
const description = screen.getByTestId('alert-description')
|
|
348
|
+
expect(description).toHaveClass('text-sm')
|
|
349
|
+
expect(description).toHaveClass('leading-5')
|
|
350
|
+
expect(description).toHaveClass('text-muted-foreground')
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
it('forwards ref correctly', () => {
|
|
354
|
+
const ref = React.createRef<HTMLParagraphElement>()
|
|
355
|
+
render(<AlertDescription ref={ref} data-testid="alert-description">Description</AlertDescription>)
|
|
356
|
+
expect(ref.current).toBeInstanceOf(HTMLDivElement)
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
it('maintains displayName', () => {
|
|
360
|
+
expect(AlertDescription.displayName).toBe('AlertDescription')
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
it('passes through HTML attributes', () => {
|
|
364
|
+
render(<AlertDescription id="alert-desc-1" data-testid="alert-description">Description</AlertDescription>)
|
|
365
|
+
const description = screen.getByTestId('alert-description')
|
|
366
|
+
expect(description).toHaveAttribute('id', 'alert-desc-1')
|
|
367
|
+
})
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
describe('Complex Combinations', () => {
|
|
371
|
+
it('renders alert with title and description', () => {
|
|
372
|
+
render(
|
|
373
|
+
<Alert variant="success" size="lg" data-testid="alert">
|
|
374
|
+
<AlertTitle>Success!</AlertTitle>
|
|
375
|
+
<AlertDescription>Your action was completed successfully.</AlertDescription>
|
|
376
|
+
</Alert>
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
const alert = screen.getByTestId('alert')
|
|
380
|
+
expect(alert).toHaveClass('bg-success/10')
|
|
381
|
+
expect(alert).toHaveClass('py-4')
|
|
382
|
+
|
|
383
|
+
expect(screen.getByText('Success!')).toBeInTheDocument()
|
|
384
|
+
expect(screen.getByText('Your action was completed successfully.')).toBeInTheDocument()
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
it('renders closable alert with all props', () => {
|
|
388
|
+
const handleClose = jest.fn()
|
|
389
|
+
render(
|
|
390
|
+
<Alert
|
|
391
|
+
variant="error"
|
|
392
|
+
size="sm"
|
|
393
|
+
radius="lg"
|
|
394
|
+
closable
|
|
395
|
+
onClose={handleClose}
|
|
396
|
+
className="custom-alert"
|
|
397
|
+
data-testid="alert"
|
|
398
|
+
>
|
|
399
|
+
<AlertTitle>Error</AlertTitle>
|
|
400
|
+
<AlertDescription>Something went wrong.</AlertDescription>
|
|
401
|
+
</Alert>
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
const alert = screen.getByTestId('alert')
|
|
405
|
+
expect(alert).toHaveClass('bg-destructive/10')
|
|
406
|
+
expect(alert).toHaveClass('py-2')
|
|
407
|
+
expect(alert).toHaveClass('rounded-lg')
|
|
408
|
+
expect(alert).toHaveClass('pr-10')
|
|
409
|
+
expect(alert).toHaveClass('custom-alert')
|
|
410
|
+
|
|
411
|
+
const closeButton = alert.querySelector('button')
|
|
412
|
+
expect(closeButton).toBeInTheDocument()
|
|
413
|
+
|
|
414
|
+
fireEvent.click(closeButton!)
|
|
415
|
+
expect(handleClose).toHaveBeenCalled()
|
|
416
|
+
})
|
|
417
|
+
|
|
418
|
+
it('renders alert without icon and with custom content', () => {
|
|
419
|
+
render(
|
|
420
|
+
<Alert variant="warning" hideIcon data-testid="alert">
|
|
421
|
+
<div>
|
|
422
|
+
<AlertTitle>Custom Warning</AlertTitle>
|
|
423
|
+
<AlertDescription>This is a custom warning message.</AlertDescription>
|
|
424
|
+
<button>Action Button</button>
|
|
425
|
+
</div>
|
|
426
|
+
</Alert>
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
const alert = screen.getByTestId('alert')
|
|
430
|
+
expect(alert.querySelector('svg')).not.toBeInTheDocument()
|
|
431
|
+
expect(screen.getByText('Custom Warning')).toBeInTheDocument()
|
|
432
|
+
expect(screen.getByText('Action Button')).toBeInTheDocument()
|
|
433
|
+
})
|
|
434
|
+
})
|
|
435
|
+
|
|
436
|
+
describe('Edge Cases', () => {
|
|
437
|
+
it('passes through HTML attributes', () => {
|
|
438
|
+
render(<Alert id="alert-1" data-custom="value" data-testid="alert">Test</Alert>)
|
|
439
|
+
const alert = screen.getByTestId('alert')
|
|
440
|
+
expect(alert).toHaveAttribute('id', 'alert-1')
|
|
441
|
+
expect(alert).toHaveAttribute('data-custom', 'value')
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
it('handles empty content gracefully', () => {
|
|
445
|
+
render(<Alert data-testid="alert"></Alert>)
|
|
446
|
+
const alert = screen.getByTestId('alert')
|
|
447
|
+
expect(alert).toBeInTheDocument()
|
|
448
|
+
expect(alert).toHaveAttribute('role', 'alert')
|
|
449
|
+
})
|
|
450
|
+
|
|
451
|
+
it('handles null children gracefully', () => {
|
|
452
|
+
render(<Alert data-testid="alert">{null}</Alert>)
|
|
453
|
+
const alert = screen.getByTestId('alert')
|
|
454
|
+
expect(alert).toBeInTheDocument()
|
|
455
|
+
})
|
|
456
|
+
|
|
457
|
+
it('handles multiple close button clicks', () => {
|
|
458
|
+
const handleClose = jest.fn()
|
|
459
|
+
render(<Alert closable onClose={handleClose} data-testid="alert">Test</Alert>)
|
|
460
|
+
const alert = screen.getByTestId('alert')
|
|
461
|
+
const closeButton = alert.querySelector('button')
|
|
462
|
+
|
|
463
|
+
fireEvent.click(closeButton!)
|
|
464
|
+
fireEvent.click(closeButton!)
|
|
465
|
+
fireEvent.click(closeButton!)
|
|
466
|
+
|
|
467
|
+
expect(handleClose).toHaveBeenCalledTimes(3)
|
|
468
|
+
})
|
|
469
|
+
|
|
470
|
+
it('renders with all variants and sizes combination', () => {
|
|
471
|
+
const variants = ['default', 'primary', 'success', 'warning', 'error', 'info'] as const
|
|
472
|
+
const sizes = ['sm', 'default', 'lg'] as const
|
|
473
|
+
|
|
474
|
+
variants.forEach((variant, variantIndex) => {
|
|
475
|
+
sizes.forEach((size, sizeIndex) => {
|
|
476
|
+
const testId = `alert-${variant}-${size}`
|
|
477
|
+
render(<Alert variant={variant} size={size} data-testid={testId}>Test {variant} {size}</Alert>)
|
|
478
|
+
const alert = screen.getByTestId(testId)
|
|
479
|
+
expect(alert).toBeInTheDocument()
|
|
480
|
+
})
|
|
481
|
+
})
|
|
482
|
+
})
|
|
483
|
+
})
|
|
484
|
+
})
|