@moontra/moonui 2.0.7 → 2.0.9
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 +26 -19
- 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,592 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react'
|
|
3
|
+
import '@testing-library/jest-dom'
|
|
4
|
+
import {
|
|
5
|
+
Collapsible,
|
|
6
|
+
CollapsibleTrigger,
|
|
7
|
+
CollapsibleContent,
|
|
8
|
+
collapsibleTriggerVariants,
|
|
9
|
+
collapsibleContentVariants,
|
|
10
|
+
} from '../collapsible'
|
|
11
|
+
|
|
12
|
+
describe('Collapsible Components', () => {
|
|
13
|
+
describe('Collapsible Component', () => {
|
|
14
|
+
it('renders correctly with default props', () => {
|
|
15
|
+
render(
|
|
16
|
+
<Collapsible data-testid="collapsible">
|
|
17
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
18
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
19
|
+
</Collapsible>
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
const collapsible = screen.getByTestId('collapsible')
|
|
23
|
+
expect(collapsible).toBeInTheDocument()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('applies custom className', () => {
|
|
27
|
+
render(
|
|
28
|
+
<Collapsible className="custom-class" data-testid="collapsible">
|
|
29
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
30
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
31
|
+
</Collapsible>
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
const collapsible = screen.getByTestId('collapsible')
|
|
35
|
+
expect(collapsible).toHaveClass('custom-class')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('forwards ref correctly', () => {
|
|
39
|
+
const ref = React.createRef<HTMLDivElement>()
|
|
40
|
+
render(
|
|
41
|
+
<Collapsible ref={ref} data-testid="collapsible">
|
|
42
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
43
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
44
|
+
</Collapsible>
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
expect(ref.current).toBeInstanceOf(HTMLDivElement)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('handles controlled state', () => {
|
|
51
|
+
const onOpenChange = jest.fn()
|
|
52
|
+
render(
|
|
53
|
+
<Collapsible open={true} onOpenChange={onOpenChange} data-testid="collapsible">
|
|
54
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
55
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
56
|
+
</Collapsible>
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
const trigger = screen.getByRole('button')
|
|
60
|
+
fireEvent.click(trigger)
|
|
61
|
+
expect(onOpenChange).toHaveBeenCalledWith(false)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('passes through HTML attributes', () => {
|
|
65
|
+
render(
|
|
66
|
+
<Collapsible data-testid="collapsible" id="collapsible-1">
|
|
67
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
68
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
69
|
+
</Collapsible>
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
const collapsible = screen.getByTestId('collapsible')
|
|
73
|
+
expect(collapsible).toHaveAttribute('id', 'collapsible-1')
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
describe('CollapsibleTrigger Component', () => {
|
|
78
|
+
it('renders correctly with default props', () => {
|
|
79
|
+
render(
|
|
80
|
+
<Collapsible>
|
|
81
|
+
<CollapsibleTrigger data-testid="trigger">Toggle</CollapsibleTrigger>
|
|
82
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
83
|
+
</Collapsible>
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
const trigger = screen.getByTestId('trigger')
|
|
87
|
+
expect(trigger).toBeInTheDocument()
|
|
88
|
+
expect(trigger).toHaveClass('flex')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('applies custom className', () => {
|
|
92
|
+
render(
|
|
93
|
+
<Collapsible>
|
|
94
|
+
<CollapsibleTrigger className="custom-trigger" data-testid="trigger">
|
|
95
|
+
Toggle
|
|
96
|
+
</CollapsibleTrigger>
|
|
97
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
98
|
+
</Collapsible>
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
const trigger = screen.getByTestId('trigger')
|
|
102
|
+
expect(trigger).toHaveClass('custom-trigger')
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('forwards ref correctly', () => {
|
|
106
|
+
const ref = React.createRef<HTMLButtonElement>()
|
|
107
|
+
render(
|
|
108
|
+
<Collapsible>
|
|
109
|
+
<CollapsibleTrigger ref={ref} data-testid="trigger">
|
|
110
|
+
Toggle
|
|
111
|
+
</CollapsibleTrigger>
|
|
112
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
113
|
+
</Collapsible>
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
expect(ref.current).toBeInstanceOf(HTMLButtonElement)
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('maintains displayName', () => {
|
|
120
|
+
expect(CollapsibleTrigger.displayName).toBe('CollapsibleTrigger')
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
it('renders default variant correctly', () => {
|
|
124
|
+
render(
|
|
125
|
+
<Collapsible>
|
|
126
|
+
<CollapsibleTrigger data-testid="trigger">Toggle</CollapsibleTrigger>
|
|
127
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
128
|
+
</Collapsible>
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
const trigger = screen.getByTestId('trigger')
|
|
132
|
+
expect(trigger).toHaveClass('text-foreground')
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('renders ghost variant correctly', () => {
|
|
136
|
+
render(
|
|
137
|
+
<Collapsible>
|
|
138
|
+
<CollapsibleTrigger variant="ghost" data-testid="trigger">
|
|
139
|
+
Toggle
|
|
140
|
+
</CollapsibleTrigger>
|
|
141
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
142
|
+
</Collapsible>
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
const trigger = screen.getByTestId('trigger')
|
|
146
|
+
expect(trigger).toHaveClass('rounded')
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
it('renders outline variant correctly', () => {
|
|
150
|
+
render(
|
|
151
|
+
<Collapsible>
|
|
152
|
+
<CollapsibleTrigger variant="outline" data-testid="trigger">
|
|
153
|
+
Toggle
|
|
154
|
+
</CollapsibleTrigger>
|
|
155
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
156
|
+
</Collapsible>
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
const trigger = screen.getByTestId('trigger')
|
|
160
|
+
expect(trigger).toHaveClass('border')
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
it('renders sm size correctly', () => {
|
|
164
|
+
render(
|
|
165
|
+
<Collapsible>
|
|
166
|
+
<CollapsibleTrigger size="sm" data-testid="trigger">
|
|
167
|
+
Toggle
|
|
168
|
+
</CollapsibleTrigger>
|
|
169
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
170
|
+
</Collapsible>
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
const trigger = screen.getByTestId('trigger')
|
|
174
|
+
expect(trigger).toHaveClass('text-xs')
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it('renders default size correctly', () => {
|
|
178
|
+
render(
|
|
179
|
+
<Collapsible>
|
|
180
|
+
<CollapsibleTrigger data-testid="trigger">Toggle</CollapsibleTrigger>
|
|
181
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
182
|
+
</Collapsible>
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
const trigger = screen.getByTestId('trigger')
|
|
186
|
+
expect(trigger).toHaveClass('text-sm')
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
it('renders md size correctly', () => {
|
|
190
|
+
render(
|
|
191
|
+
<Collapsible>
|
|
192
|
+
<CollapsibleTrigger size="md" data-testid="trigger">
|
|
193
|
+
Toggle
|
|
194
|
+
</CollapsibleTrigger>
|
|
195
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
196
|
+
</Collapsible>
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
const trigger = screen.getByTestId('trigger')
|
|
200
|
+
expect(trigger).toHaveClass('text-base')
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
it('renders lg size correctly', () => {
|
|
204
|
+
render(
|
|
205
|
+
<Collapsible>
|
|
206
|
+
<CollapsibleTrigger size="lg" data-testid="trigger">
|
|
207
|
+
Toggle
|
|
208
|
+
</CollapsibleTrigger>
|
|
209
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
210
|
+
</Collapsible>
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
const trigger = screen.getByTestId('trigger')
|
|
214
|
+
expect(trigger).toHaveClass('text-lg')
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
it('renders chevron icon', () => {
|
|
218
|
+
render(
|
|
219
|
+
<Collapsible>
|
|
220
|
+
<CollapsibleTrigger data-testid="trigger">Toggle</CollapsibleTrigger>
|
|
221
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
222
|
+
</Collapsible>
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
const trigger = screen.getByTestId('trigger')
|
|
226
|
+
const chevron = trigger.querySelector('svg')
|
|
227
|
+
expect(chevron).toBeInTheDocument()
|
|
228
|
+
expect(chevron).toHaveClass('h-4')
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
it('handles click events', () => {
|
|
232
|
+
const onClick = jest.fn()
|
|
233
|
+
render(
|
|
234
|
+
<Collapsible>
|
|
235
|
+
<CollapsibleTrigger onClick={onClick} data-testid="trigger">
|
|
236
|
+
Toggle
|
|
237
|
+
</CollapsibleTrigger>
|
|
238
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
239
|
+
</Collapsible>
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
const trigger = screen.getByTestId('trigger')
|
|
243
|
+
fireEvent.click(trigger)
|
|
244
|
+
expect(onClick).toHaveBeenCalled()
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
it('passes through HTML attributes', () => {
|
|
248
|
+
render(
|
|
249
|
+
<Collapsible>
|
|
250
|
+
<CollapsibleTrigger data-testid="trigger" id="trigger-1">
|
|
251
|
+
Toggle
|
|
252
|
+
</CollapsibleTrigger>
|
|
253
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
254
|
+
</Collapsible>
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
const trigger = screen.getByTestId('trigger')
|
|
258
|
+
expect(trigger).toHaveAttribute('id', 'trigger-1')
|
|
259
|
+
})
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
describe('CollapsibleContent Component', () => {
|
|
263
|
+
it('renders correctly with default props', () => {
|
|
264
|
+
render(
|
|
265
|
+
<Collapsible defaultOpen>
|
|
266
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
267
|
+
<CollapsibleContent data-testid="content">Content</CollapsibleContent>
|
|
268
|
+
</Collapsible>
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
const content = screen.getByTestId('content')
|
|
272
|
+
expect(content).toBeInTheDocument()
|
|
273
|
+
expect(content).toHaveClass('overflow-hidden')
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
it('applies custom className', () => {
|
|
277
|
+
render(
|
|
278
|
+
<Collapsible defaultOpen>
|
|
279
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
280
|
+
<CollapsibleContent className="custom-content" data-testid="content">
|
|
281
|
+
Content
|
|
282
|
+
</CollapsibleContent>
|
|
283
|
+
</Collapsible>
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
const content = screen.getByTestId('content')
|
|
287
|
+
expect(content).toHaveClass('custom-content')
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
it('forwards ref correctly', () => {
|
|
291
|
+
const ref = React.createRef<HTMLDivElement>()
|
|
292
|
+
render(
|
|
293
|
+
<Collapsible defaultOpen>
|
|
294
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
295
|
+
<CollapsibleContent ref={ref} data-testid="content">
|
|
296
|
+
Content
|
|
297
|
+
</CollapsibleContent>
|
|
298
|
+
</Collapsible>
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
expect(ref.current).toBeInstanceOf(HTMLDivElement)
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
it('maintains displayName', () => {
|
|
305
|
+
expect(CollapsibleContent.displayName).toBe('CollapsibleContent')
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
it('renders default variant correctly', () => {
|
|
309
|
+
render(
|
|
310
|
+
<Collapsible defaultOpen>
|
|
311
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
312
|
+
<CollapsibleContent data-testid="content">Content</CollapsibleContent>
|
|
313
|
+
</Collapsible>
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
const content = screen.getByTestId('content')
|
|
317
|
+
expect(content).toHaveClass('text-muted-foreground')
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
it('renders ghost variant correctly', () => {
|
|
321
|
+
render(
|
|
322
|
+
<Collapsible defaultOpen>
|
|
323
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
324
|
+
<CollapsibleContent variant="ghost" data-testid="content">
|
|
325
|
+
Content
|
|
326
|
+
</CollapsibleContent>
|
|
327
|
+
</Collapsible>
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
const content = screen.getByTestId('content')
|
|
331
|
+
expect(content).toHaveClass('rounded-b')
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
it('renders outline variant correctly', () => {
|
|
335
|
+
render(
|
|
336
|
+
<Collapsible defaultOpen>
|
|
337
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
338
|
+
<CollapsibleContent variant="outline" data-testid="content">
|
|
339
|
+
Content
|
|
340
|
+
</CollapsibleContent>
|
|
341
|
+
</Collapsible>
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
const content = screen.getByTestId('content')
|
|
345
|
+
expect(content).toHaveClass('border')
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
it('renders sm size correctly', () => {
|
|
349
|
+
render(
|
|
350
|
+
<Collapsible defaultOpen>
|
|
351
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
352
|
+
<CollapsibleContent size="sm" data-testid="content">
|
|
353
|
+
Content
|
|
354
|
+
</CollapsibleContent>
|
|
355
|
+
</Collapsible>
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
const content = screen.getByTestId('content')
|
|
359
|
+
expect(content).toHaveClass('text-xs')
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
it('renders default size correctly', () => {
|
|
363
|
+
render(
|
|
364
|
+
<Collapsible defaultOpen>
|
|
365
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
366
|
+
<CollapsibleContent data-testid="content">Content</CollapsibleContent>
|
|
367
|
+
</Collapsible>
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
const content = screen.getByTestId('content')
|
|
371
|
+
expect(content).toHaveClass('text-sm')
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
it('renders md size correctly', () => {
|
|
375
|
+
render(
|
|
376
|
+
<Collapsible defaultOpen>
|
|
377
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
378
|
+
<CollapsibleContent size="md" data-testid="content">
|
|
379
|
+
Content
|
|
380
|
+
</CollapsibleContent>
|
|
381
|
+
</Collapsible>
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
const content = screen.getByTestId('content')
|
|
385
|
+
expect(content).toHaveClass('text-base')
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
it('renders lg size correctly', () => {
|
|
389
|
+
render(
|
|
390
|
+
<Collapsible defaultOpen>
|
|
391
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
392
|
+
<CollapsibleContent size="lg" data-testid="content">
|
|
393
|
+
Content
|
|
394
|
+
</CollapsibleContent>
|
|
395
|
+
</Collapsible>
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
const content = screen.getByTestId('content')
|
|
399
|
+
expect(content).toHaveClass('text-lg')
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
it('renders content wrapper with padding', () => {
|
|
403
|
+
render(
|
|
404
|
+
<Collapsible defaultOpen>
|
|
405
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
406
|
+
<CollapsibleContent data-testid="content">Content</CollapsibleContent>
|
|
407
|
+
</Collapsible>
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
const content = screen.getByTestId('content')
|
|
411
|
+
const wrapper = content.querySelector('.p-4')
|
|
412
|
+
expect(wrapper).toBeInTheDocument()
|
|
413
|
+
expect(wrapper).toHaveTextContent('Content')
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
it('passes through HTML attributes', () => {
|
|
417
|
+
render(
|
|
418
|
+
<Collapsible defaultOpen>
|
|
419
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
420
|
+
<CollapsibleContent data-testid="content" id="content-1">
|
|
421
|
+
Content
|
|
422
|
+
</CollapsibleContent>
|
|
423
|
+
</Collapsible>
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
const content = screen.getByTestId('content')
|
|
427
|
+
expect(content).toHaveAttribute('id', 'content-1')
|
|
428
|
+
})
|
|
429
|
+
})
|
|
430
|
+
|
|
431
|
+
describe('Variant Functions', () => {
|
|
432
|
+
it('collapsibleTriggerVariants generates correct classes', () => {
|
|
433
|
+
expect(collapsibleTriggerVariants()).toContain('flex w-full items-center justify-between')
|
|
434
|
+
expect(collapsibleTriggerVariants({ variant: 'ghost' })).toContain('rounded')
|
|
435
|
+
expect(collapsibleTriggerVariants({ size: 'sm' })).toContain('text-xs py-2 px-3')
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
it('collapsibleContentVariants generates correct classes', () => {
|
|
439
|
+
expect(collapsibleContentVariants()).toContain('overflow-hidden transition-all')
|
|
440
|
+
expect(collapsibleContentVariants({ variant: 'outline' })).toContain('border')
|
|
441
|
+
expect(collapsibleContentVariants({ size: 'lg' })).toContain('text-lg')
|
|
442
|
+
})
|
|
443
|
+
})
|
|
444
|
+
|
|
445
|
+
describe('Complex Combinations', () => {
|
|
446
|
+
it('renders with all props and variants', () => {
|
|
447
|
+
render(
|
|
448
|
+
<Collapsible defaultOpen className="custom-collapsible" data-testid="collapsible">
|
|
449
|
+
<CollapsibleTrigger
|
|
450
|
+
variant="outline"
|
|
451
|
+
size="lg"
|
|
452
|
+
className="custom-trigger"
|
|
453
|
+
data-testid="trigger"
|
|
454
|
+
>
|
|
455
|
+
Toggle Content
|
|
456
|
+
</CollapsibleTrigger>
|
|
457
|
+
<CollapsibleContent
|
|
458
|
+
variant="outline"
|
|
459
|
+
size="lg"
|
|
460
|
+
className="custom-content"
|
|
461
|
+
data-testid="content"
|
|
462
|
+
>
|
|
463
|
+
This is the collapsible content
|
|
464
|
+
</CollapsibleContent>
|
|
465
|
+
</Collapsible>
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
const collapsible = screen.getByTestId('collapsible')
|
|
469
|
+
const trigger = screen.getByTestId('trigger')
|
|
470
|
+
const content = screen.getByTestId('content')
|
|
471
|
+
|
|
472
|
+
expect(collapsible).toHaveClass('custom-collapsible')
|
|
473
|
+
expect(trigger).toHaveClass('custom-trigger')
|
|
474
|
+
expect(content).toHaveClass('custom-content')
|
|
475
|
+
})
|
|
476
|
+
|
|
477
|
+
it('handles toggle functionality', () => {
|
|
478
|
+
render(
|
|
479
|
+
<Collapsible data-testid="collapsible">
|
|
480
|
+
<CollapsibleTrigger data-testid="trigger">Toggle</CollapsibleTrigger>
|
|
481
|
+
<CollapsibleContent data-testid="content">Content</CollapsibleContent>
|
|
482
|
+
</Collapsible>
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
const trigger = screen.getByTestId('trigger')
|
|
486
|
+
|
|
487
|
+
// Initially closed
|
|
488
|
+
expect(screen.queryByText('Content')).not.toBeInTheDocument()
|
|
489
|
+
|
|
490
|
+
// Click to open
|
|
491
|
+
fireEvent.click(trigger)
|
|
492
|
+
expect(screen.getByText('Content')).toBeInTheDocument()
|
|
493
|
+
|
|
494
|
+
// Click to close
|
|
495
|
+
fireEvent.click(trigger)
|
|
496
|
+
expect(screen.queryByText('Content')).not.toBeInTheDocument()
|
|
497
|
+
})
|
|
498
|
+
|
|
499
|
+
it('renders multiple collapsibles independently', () => {
|
|
500
|
+
render(
|
|
501
|
+
<div>
|
|
502
|
+
<Collapsible data-testid="collapsible-1">
|
|
503
|
+
<CollapsibleTrigger data-testid="trigger-1">Toggle 1</CollapsibleTrigger>
|
|
504
|
+
<CollapsibleContent>Content 1</CollapsibleContent>
|
|
505
|
+
</Collapsible>
|
|
506
|
+
<Collapsible data-testid="collapsible-2">
|
|
507
|
+
<CollapsibleTrigger data-testid="trigger-2">Toggle 2</CollapsibleTrigger>
|
|
508
|
+
<CollapsibleContent>Content 2</CollapsibleContent>
|
|
509
|
+
</Collapsible>
|
|
510
|
+
</div>
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
const trigger1 = screen.getByTestId('trigger-1')
|
|
514
|
+
const trigger2 = screen.getByTestId('trigger-2')
|
|
515
|
+
|
|
516
|
+
// Open first collapsible
|
|
517
|
+
fireEvent.click(trigger1)
|
|
518
|
+
expect(screen.getByText('Content 1')).toBeInTheDocument()
|
|
519
|
+
expect(screen.queryByText('Content 2')).not.toBeInTheDocument()
|
|
520
|
+
|
|
521
|
+
// Open second collapsible
|
|
522
|
+
fireEvent.click(trigger2)
|
|
523
|
+
expect(screen.getByText('Content 1')).toBeInTheDocument()
|
|
524
|
+
expect(screen.getByText('Content 2')).toBeInTheDocument()
|
|
525
|
+
})
|
|
526
|
+
})
|
|
527
|
+
|
|
528
|
+
describe('Edge Cases', () => {
|
|
529
|
+
it('handles empty content', () => {
|
|
530
|
+
render(
|
|
531
|
+
<Collapsible defaultOpen>
|
|
532
|
+
<CollapsibleTrigger data-testid="trigger">Toggle</CollapsibleTrigger>
|
|
533
|
+
<CollapsibleContent data-testid="content"></CollapsibleContent>
|
|
534
|
+
</Collapsible>
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
const content = screen.getByTestId('content')
|
|
538
|
+
expect(content).toBeInTheDocument()
|
|
539
|
+
})
|
|
540
|
+
|
|
541
|
+
it('handles complex nested content', () => {
|
|
542
|
+
render(
|
|
543
|
+
<Collapsible defaultOpen>
|
|
544
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
545
|
+
<CollapsibleContent data-testid="content">
|
|
546
|
+
<div>
|
|
547
|
+
<h3>Nested Title</h3>
|
|
548
|
+
<p>Nested paragraph</p>
|
|
549
|
+
<ul>
|
|
550
|
+
<li>Item 1</li>
|
|
551
|
+
<li>Item 2</li>
|
|
552
|
+
</ul>
|
|
553
|
+
</div>
|
|
554
|
+
</CollapsibleContent>
|
|
555
|
+
</Collapsible>
|
|
556
|
+
)
|
|
557
|
+
|
|
558
|
+
expect(screen.getByText('Nested Title')).toBeInTheDocument()
|
|
559
|
+
expect(screen.getByText('Nested paragraph')).toBeInTheDocument()
|
|
560
|
+
expect(screen.getByText('Item 1')).toBeInTheDocument()
|
|
561
|
+
})
|
|
562
|
+
|
|
563
|
+
it('handles disabled state', () => {
|
|
564
|
+
render(
|
|
565
|
+
<Collapsible>
|
|
566
|
+
<CollapsibleTrigger disabled data-testid="trigger">
|
|
567
|
+
Toggle
|
|
568
|
+
</CollapsibleTrigger>
|
|
569
|
+
<CollapsibleContent>Content</CollapsibleContent>
|
|
570
|
+
</Collapsible>
|
|
571
|
+
)
|
|
572
|
+
|
|
573
|
+
const trigger = screen.getByTestId('trigger')
|
|
574
|
+
expect(trigger).toBeDisabled()
|
|
575
|
+
})
|
|
576
|
+
|
|
577
|
+
it('handles null and undefined children', () => {
|
|
578
|
+
render(
|
|
579
|
+
<Collapsible defaultOpen>
|
|
580
|
+
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
|
|
581
|
+
<CollapsibleContent data-testid="content">
|
|
582
|
+
{null}
|
|
583
|
+
{undefined}
|
|
584
|
+
Valid content
|
|
585
|
+
</CollapsibleContent>
|
|
586
|
+
</Collapsible>
|
|
587
|
+
)
|
|
588
|
+
|
|
589
|
+
expect(screen.getByText('Valid content')).toBeInTheDocument()
|
|
590
|
+
})
|
|
591
|
+
})
|
|
592
|
+
})
|