@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.
Files changed (94) hide show
  1. package/package.json +26 -19
  2. package/src/__tests__/use-intersection-observer.test.tsx +216 -0
  3. package/src/__tests__/use-local-storage.test.tsx +174 -0
  4. package/src/__tests__/use-pro-access.test.tsx +183 -0
  5. package/src/components/ui/__tests__/accordion.test.tsx +571 -0
  6. package/src/components/ui/__tests__/alert.test.tsx +484 -0
  7. package/src/components/ui/__tests__/aspect-ratio.test.tsx +492 -0
  8. package/src/components/ui/__tests__/avatar.test.tsx +382 -0
  9. package/src/components/ui/__tests__/badge.test.tsx +364 -0
  10. package/src/components/ui/__tests__/breadcrumb.test.tsx +687 -0
  11. package/src/components/ui/__tests__/button.test.tsx +91 -0
  12. package/src/components/ui/__tests__/card.test.tsx +104 -0
  13. package/src/components/ui/__tests__/checkbox.test.tsx +591 -0
  14. package/src/components/ui/__tests__/collapsible.test.tsx +592 -0
  15. package/src/components/ui/__tests__/color-picker.test.tsx +365 -0
  16. package/src/components/ui/__tests__/command.test.tsx +677 -0
  17. package/src/components/ui/__tests__/data-table.test.tsx +256 -0
  18. package/src/components/ui/__tests__/date-picker.test.tsx +320 -0
  19. package/src/components/ui/__tests__/dialog.test.tsx +764 -0
  20. package/src/components/ui/__tests__/input.test.tsx +318 -0
  21. package/src/components/ui/__tests__/label.test.tsx +103 -0
  22. package/src/components/ui/__tests__/popover.test.tsx +637 -0
  23. package/src/components/ui/__tests__/progress.test.tsx +382 -0
  24. package/src/components/ui/__tests__/radio-group.test.tsx +555 -0
  25. package/src/components/ui/__tests__/select.test.tsx +705 -0
  26. package/src/components/ui/__tests__/skeleton.test.tsx +253 -0
  27. package/src/components/ui/__tests__/slider.test.tsx +493 -0
  28. package/src/components/ui/__tests__/switch.test.tsx +372 -0
  29. package/src/components/ui/__tests__/table.test.tsx +824 -0
  30. package/src/components/ui/__tests__/tabs.test.tsx +887 -0
  31. package/src/components/ui/__tests__/toast.test.tsx +458 -0
  32. package/src/components/ui/__tests__/tooltip.test.tsx +583 -0
  33. package/src/components/ui/accordion.tsx +63 -0
  34. package/src/components/ui/alert.tsx +130 -0
  35. package/src/components/ui/aspect-ratio.tsx +72 -0
  36. package/src/components/ui/avatar.tsx +135 -0
  37. package/src/components/ui/badge.tsx +225 -0
  38. package/src/components/ui/breadcrumb.tsx +207 -0
  39. package/src/components/ui/button.stories.tsx +162 -0
  40. package/src/components/ui/button.tsx +221 -0
  41. package/src/components/ui/calendar.tsx +262 -0
  42. package/src/components/ui/card.stories.tsx +208 -0
  43. package/src/components/ui/card.tsx +141 -0
  44. package/src/components/ui/checkbox.tsx +256 -0
  45. package/src/components/ui/collapsible.tsx +129 -0
  46. package/src/components/ui/color-picker.tsx +664 -0
  47. package/src/components/ui/command.tsx +218 -0
  48. package/src/components/ui/data-table.stories.tsx +509 -0
  49. package/src/components/ui/data-table.tsx +623 -0
  50. package/src/components/ui/date-picker.stories.tsx +321 -0
  51. package/src/components/ui/date-picker.tsx +603 -0
  52. package/src/components/ui/dialog.tsx +332 -0
  53. package/src/components/ui/dropdown-menu.tsx +200 -0
  54. package/src/components/ui/file-upload.tsx +400 -0
  55. package/src/components/ui/github-stars.tsx +201 -0
  56. package/src/components/ui/index.ts +12 -0
  57. package/src/components/ui/input.stories.tsx +255 -0
  58. package/src/components/ui/input.tsx +219 -0
  59. package/src/components/ui/label.tsx +26 -0
  60. package/src/components/ui/locked-component.tsx +215 -0
  61. package/src/components/ui/moon-logo.tsx +97 -0
  62. package/src/components/ui/pagination.tsx +116 -0
  63. package/src/components/ui/popover.tsx +183 -0
  64. package/src/components/ui/progress.tsx +182 -0
  65. package/src/components/ui/radio-group.tsx +243 -0
  66. package/src/components/ui/select.tsx +273 -0
  67. package/src/components/ui/separator.tsx +140 -0
  68. package/src/components/ui/simple-editor.tsx +652 -0
  69. package/src/components/ui/skeleton.tsx +351 -0
  70. package/src/components/ui/slider.tsx +351 -0
  71. package/src/components/ui/switch.tsx +83 -0
  72. package/src/components/ui/table.tsx +322 -0
  73. package/src/components/ui/tabs.tsx +195 -0
  74. package/src/components/ui/textarea.tsx +46 -0
  75. package/src/components/ui/toast.tsx +313 -0
  76. package/src/components/ui/toggle.tsx +47 -0
  77. package/src/components/ui/tooltip.tsx +152 -0
  78. package/src/docs/theme-system.md +1194 -0
  79. package/src/index.tsx +39 -0
  80. package/src/lib/micro-interactions.ts +255 -0
  81. package/src/lib/theme.tsx +398 -0
  82. package/src/lib/utils.ts +69 -0
  83. package/src/styles/design-system.css +365 -0
  84. package/src/styles/index.css +4 -0
  85. package/src/styles/tailwind.css +6 -0
  86. package/src/styles/tokens.css +453 -0
  87. package/src/use-intersection-observer.tsx +154 -0
  88. package/src/use-local-storage.tsx +71 -0
  89. package/src/use-paddle.ts +138 -0
  90. package/src/use-performance-optimizer.ts +379 -0
  91. package/src/use-pro-access.ts +141 -0
  92. package/src/use-scroll-animation.ts +221 -0
  93. package/src/use-subscription.ts +37 -0
  94. package/src/use-toast.ts +32 -0
@@ -0,0 +1,555 @@
1
+ import React from 'react'
2
+ import { render, screen, fireEvent } from '@testing-library/react'
3
+ import '@testing-library/jest-dom'
4
+ import {
5
+ RadioGroup,
6
+ RadioGroupItem,
7
+ RadioLabel,
8
+ RadioItemWithLabel,
9
+ } from '../radio-group'
10
+
11
+ describe('RadioGroup Components', () => {
12
+ describe('RadioGroup Component', () => {
13
+ it('renders correctly with default props', () => {
14
+ render(
15
+ <RadioGroup data-testid="radio-group">
16
+ <RadioGroupItem value="option1" />
17
+ <RadioGroupItem value="option2" />
18
+ </RadioGroup>
19
+ )
20
+
21
+ const radioGroup = screen.getByTestId('radio-group')
22
+ expect(radioGroup).toBeInTheDocument()
23
+ expect(radioGroup).toHaveAttribute('role', 'radiogroup')
24
+ expect(radioGroup).toHaveClass('grid', 'gap-2')
25
+ })
26
+
27
+ it('applies custom className', () => {
28
+ render(
29
+ <RadioGroup className="custom-class" data-testid="radio-group">
30
+ <RadioGroupItem value="option1" />
31
+ </RadioGroup>
32
+ )
33
+
34
+ const radioGroup = screen.getByTestId('radio-group')
35
+ expect(radioGroup).toHaveClass('custom-class')
36
+ })
37
+
38
+ it('forwards ref correctly', () => {
39
+ const ref = React.createRef<HTMLDivElement>()
40
+ render(
41
+ <RadioGroup ref={ref} data-testid="radio-group">
42
+ <RadioGroupItem value="option1" />
43
+ </RadioGroup>
44
+ )
45
+
46
+ expect(ref.current).toBeInstanceOf(HTMLDivElement)
47
+ })
48
+
49
+ it('handles controlled state', () => {
50
+ const onValueChange = jest.fn()
51
+ render(
52
+ <RadioGroup value="option2" onValueChange={onValueChange} data-testid="radio-group">
53
+ <RadioGroupItem value="option1" />
54
+ <RadioGroupItem value="option2" />
55
+ </RadioGroup>
56
+ )
57
+
58
+ const option1 = screen.getByDisplayValue('option1')
59
+ const option2 = screen.getByDisplayValue('option2')
60
+
61
+ expect(option1).not.toBeChecked()
62
+ expect(option2).toBeChecked()
63
+
64
+ fireEvent.click(option1)
65
+ expect(onValueChange).toHaveBeenCalledWith('option1')
66
+ })
67
+
68
+ it('handles disabled state', () => {
69
+ render(
70
+ <RadioGroup disabled data-testid="radio-group">
71
+ <RadioGroupItem value="option1" />
72
+ <RadioGroupItem value="option2" />
73
+ </RadioGroup>
74
+ )
75
+
76
+ const option1 = screen.getByDisplayValue('option1')
77
+ const option2 = screen.getByDisplayValue('option2')
78
+
79
+ expect(option1).toBeDisabled()
80
+ expect(option2).toBeDisabled()
81
+ })
82
+
83
+ it('passes through HTML attributes', () => {
84
+ render(
85
+ <RadioGroup data-testid="radio-group" id="radio-group-1">
86
+ <RadioGroupItem value="option1" />
87
+ </RadioGroup>
88
+ )
89
+
90
+ const radioGroup = screen.getByTestId('radio-group')
91
+ expect(radioGroup).toHaveAttribute('id', 'radio-group-1')
92
+ })
93
+
94
+ it('maintains displayName', () => {
95
+ expect(RadioGroup.displayName).toBe('RadioGroup')
96
+ })
97
+ })
98
+
99
+ describe('RadioGroupItem Component', () => {
100
+ it('renders correctly with default props', () => {
101
+ render(
102
+ <RadioGroup>
103
+ <RadioGroupItem value="test" data-testid="radio-item" />
104
+ </RadioGroup>
105
+ )
106
+
107
+ const radioItem = screen.getByDisplayValue('test')
108
+ expect(radioItem).toBeInTheDocument()
109
+ expect(radioItem).toHaveAttribute('type', 'radio')
110
+ expect(radioItem).toHaveAttribute('value', 'test')
111
+ })
112
+
113
+ it('applies custom className to label', () => {
114
+ render(
115
+ <RadioGroup>
116
+ <RadioGroupItem value="test" className="custom-radio" />
117
+ </RadioGroup>
118
+ )
119
+
120
+ const label = screen.getByDisplayValue('test').nextElementSibling
121
+ expect(label).toHaveClass('custom-radio')
122
+ })
123
+
124
+ it('forwards ref correctly', () => {
125
+ const ref = React.createRef<HTMLInputElement>()
126
+ render(
127
+ <RadioGroup>
128
+ <RadioGroupItem ref={ref} value="test" />
129
+ </RadioGroup>
130
+ )
131
+
132
+ expect(ref.current).toBeInstanceOf(HTMLInputElement)
133
+ })
134
+
135
+ it('maintains displayName', () => {
136
+ expect(RadioGroupItem.displayName).toBe('RadioGroupItem')
137
+ })
138
+
139
+ it('renders default variant correctly', () => {
140
+ render(
141
+ <RadioGroup>
142
+ <RadioGroupItem value="test" />
143
+ </RadioGroup>
144
+ )
145
+
146
+ const label = screen.getByDisplayValue('test').nextElementSibling
147
+ expect(label).toHaveClass('border-border', 'bg-background', 'text-primary')
148
+ })
149
+
150
+ it('renders outline variant correctly', () => {
151
+ render(
152
+ <RadioGroup>
153
+ <RadioGroupItem value="test" variant="outline" />
154
+ </RadioGroup>
155
+ )
156
+
157
+ const label = screen.getByDisplayValue('test').nextElementSibling
158
+ expect(label).toHaveClass('border-border', 'bg-transparent', 'text-primary')
159
+ })
160
+
161
+ it('renders filled variant correctly', () => {
162
+ render(
163
+ <RadioGroup>
164
+ <RadioGroupItem value="test" variant="filled" />
165
+ </RadioGroup>
166
+ )
167
+
168
+ const label = screen.getByDisplayValue('test').nextElementSibling
169
+ expect(label).toHaveClass('border-primary', 'bg-primary/10', 'text-primary')
170
+ })
171
+
172
+ it('renders sm size correctly', () => {
173
+ render(
174
+ <RadioGroup>
175
+ <RadioGroupItem value="test" size="sm" />
176
+ </RadioGroup>
177
+ )
178
+
179
+ const label = screen.getByDisplayValue('test').nextElementSibling
180
+ expect(label).toHaveClass('h-3.5', 'w-3.5')
181
+ })
182
+
183
+ it('renders default size correctly', () => {
184
+ render(
185
+ <RadioGroup>
186
+ <RadioGroupItem value="test" />
187
+ </RadioGroup>
188
+ )
189
+
190
+ const label = screen.getByDisplayValue('test').nextElementSibling
191
+ expect(label).toHaveClass('h-4', 'w-4')
192
+ })
193
+
194
+ it('renders md size correctly', () => {
195
+ render(
196
+ <RadioGroup>
197
+ <RadioGroupItem value="test" size="md" />
198
+ </RadioGroup>
199
+ )
200
+
201
+ const label = screen.getByDisplayValue('test').nextElementSibling
202
+ expect(label).toHaveClass('h-5', 'w-5')
203
+ })
204
+
205
+ it('renders lg size correctly', () => {
206
+ render(
207
+ <RadioGroup>
208
+ <RadioGroupItem value="test" size="lg" />
209
+ </RadioGroup>
210
+ )
211
+
212
+ const label = screen.getByDisplayValue('test').nextElementSibling
213
+ expect(label).toHaveClass('h-6', 'w-6')
214
+ })
215
+
216
+ it('renders custom indicator when checked', () => {
217
+ const CustomIndicator = () => <span data-testid="custom-indicator">✓</span>
218
+ render(
219
+ <RadioGroup value="test">
220
+ <RadioGroupItem value="test" indicator={<CustomIndicator />} />
221
+ </RadioGroup>
222
+ )
223
+
224
+ expect(screen.getByTestId('custom-indicator')).toBeInTheDocument()
225
+ })
226
+
227
+ it('renders default Circle indicator when checked', () => {
228
+ render(
229
+ <RadioGroup value="test">
230
+ <RadioGroupItem value="test" />
231
+ </RadioGroup>
232
+ )
233
+
234
+ const label = screen.getByDisplayValue('test').nextElementSibling
235
+ const indicator = label?.querySelector('svg')
236
+ expect(indicator).toBeInTheDocument()
237
+ })
238
+
239
+ it('handles disabled state', () => {
240
+ render(
241
+ <RadioGroup>
242
+ <RadioGroupItem value="test" disabled />
243
+ </RadioGroup>
244
+ )
245
+
246
+ const radioItem = screen.getByDisplayValue('test')
247
+ expect(radioItem).toBeDisabled()
248
+
249
+ const label = radioItem.nextElementSibling
250
+ expect(label).toHaveClass('cursor-not-allowed', 'opacity-50')
251
+ })
252
+
253
+ it('handles click events', () => {
254
+ const onValueChange = jest.fn()
255
+ render(
256
+ <RadioGroup onValueChange={onValueChange}>
257
+ <RadioGroupItem value="test" />
258
+ </RadioGroup>
259
+ )
260
+
261
+ const radioItem = screen.getByDisplayValue('test')
262
+ fireEvent.click(radioItem)
263
+ expect(onValueChange).toHaveBeenCalledWith('test')
264
+ })
265
+
266
+ it('handles onChange callback integration', () => {
267
+ const onValueChange = jest.fn()
268
+ render(
269
+ <RadioGroup onValueChange={onValueChange}>
270
+ <RadioGroupItem value="test" />
271
+ </RadioGroup>
272
+ )
273
+
274
+ const radioItem = screen.getByDisplayValue('test')
275
+
276
+ // Click the radio item to trigger change
277
+ fireEvent.click(radioItem)
278
+
279
+ // onValueChange should be called with the value
280
+ expect(onValueChange).toHaveBeenCalledWith('test')
281
+ })
282
+
283
+ it('passes through HTML attributes', () => {
284
+ render(
285
+ <RadioGroup>
286
+ <RadioGroupItem value="test" id="radio-1" data-custom="value" />
287
+ </RadioGroup>
288
+ )
289
+
290
+ const radioItem = screen.getByDisplayValue('test')
291
+ expect(radioItem).toHaveAttribute('id', 'radio-1')
292
+ expect(radioItem).toHaveAttribute('data-custom', 'value')
293
+ })
294
+ })
295
+
296
+ describe('RadioLabel Component', () => {
297
+ it('renders correctly with default props', () => {
298
+ render(<RadioLabel htmlFor="radio-1">Test Label</RadioLabel>)
299
+
300
+ const label = screen.getByText('Test Label')
301
+ expect(label).toBeInTheDocument()
302
+ expect(label).toHaveAttribute('for', 'radio-1')
303
+ expect(label).toHaveClass('text-sm', 'font-medium', 'leading-none', 'ml-2', 'text-foreground')
304
+ })
305
+
306
+ it('applies custom className', () => {
307
+ render(<RadioLabel className="custom-label">Test Label</RadioLabel>)
308
+
309
+ const label = screen.getByText('Test Label')
310
+ expect(label).toHaveClass('custom-label')
311
+ })
312
+
313
+ it('forwards ref correctly', () => {
314
+ const ref = React.createRef<HTMLLabelElement>()
315
+ render(<RadioLabel ref={ref}>Test Label</RadioLabel>)
316
+
317
+ expect(ref.current).toBeInstanceOf(HTMLLabelElement)
318
+ })
319
+
320
+ it('handles disabled state', () => {
321
+ render(<RadioLabel disabled>Test Label</RadioLabel>)
322
+
323
+ const label = screen.getByText('Test Label')
324
+ expect(label).toHaveClass('cursor-not-allowed', 'opacity-70')
325
+ })
326
+
327
+ it('passes through HTML attributes', () => {
328
+ render(<RadioLabel id="label-1" data-custom="value">Test Label</RadioLabel>)
329
+
330
+ const label = screen.getByText('Test Label')
331
+ expect(label).toHaveAttribute('id', 'label-1')
332
+ expect(label).toHaveAttribute('data-custom', 'value')
333
+ })
334
+
335
+ it('maintains displayName', () => {
336
+ expect(RadioLabel.displayName).toBe('RadioLabel')
337
+ })
338
+ })
339
+
340
+ describe('RadioItemWithLabel Component', () => {
341
+ it('renders correctly with default props', () => {
342
+ render(
343
+ <RadioGroup>
344
+ <RadioItemWithLabel value="test" label="Test Option" />
345
+ </RadioGroup>
346
+ )
347
+
348
+ const radioItem = screen.getByDisplayValue('test')
349
+ const label = screen.getByText('Test Option')
350
+
351
+ expect(radioItem).toBeInTheDocument()
352
+ expect(label).toBeInTheDocument()
353
+ expect(label).toHaveAttribute('for', radioItem.id)
354
+ })
355
+
356
+ it('applies custom labelClassName', () => {
357
+ render(
358
+ <RadioGroup>
359
+ <RadioItemWithLabel value="test" label="Test Option" labelClassName="custom-label" />
360
+ </RadioGroup>
361
+ )
362
+
363
+ const label = screen.getByText('Test Option')
364
+ expect(label).toHaveClass('custom-label')
365
+ })
366
+
367
+ it('forwards ref correctly', () => {
368
+ const ref = React.createRef<HTMLInputElement>()
369
+ render(
370
+ <RadioGroup>
371
+ <RadioItemWithLabel ref={ref} value="test" label="Test Option" />
372
+ </RadioGroup>
373
+ )
374
+
375
+ expect(ref.current).toBeInstanceOf(HTMLInputElement)
376
+ })
377
+
378
+ it('handles disabled state', () => {
379
+ render(
380
+ <RadioGroup>
381
+ <RadioItemWithLabel value="test" label="Test Option" disabled />
382
+ </RadioGroup>
383
+ )
384
+
385
+ const radioItem = screen.getByDisplayValue('test')
386
+ const label = screen.getByText('Test Option')
387
+
388
+ expect(radioItem).toBeDisabled()
389
+ expect(label).toHaveClass('cursor-not-allowed', 'opacity-70')
390
+ })
391
+
392
+ it('uses custom id when provided', () => {
393
+ render(
394
+ <RadioGroup>
395
+ <RadioItemWithLabel value="test" label="Test Option" id="custom-id" />
396
+ </RadioGroup>
397
+ )
398
+
399
+ const radioItem = screen.getByDisplayValue('test')
400
+ const label = screen.getByText('Test Option')
401
+
402
+ expect(radioItem).toHaveAttribute('id', 'custom-id')
403
+ expect(label).toHaveAttribute('for', 'custom-id')
404
+ })
405
+
406
+ it('generates unique id when not provided', () => {
407
+ render(
408
+ <RadioGroup>
409
+ <RadioItemWithLabel value="test1" label="Test Option 1" />
410
+ <RadioItemWithLabel value="test2" label="Test Option 2" />
411
+ </RadioGroup>
412
+ )
413
+
414
+ const radioItem1 = screen.getByDisplayValue('test1')
415
+ const radioItem2 = screen.getByDisplayValue('test2')
416
+ const label1 = screen.getByText('Test Option 1')
417
+ const label2 = screen.getByText('Test Option 2')
418
+
419
+ expect(radioItem1.id).not.toBe(radioItem2.id)
420
+ expect(label1.getAttribute('for')).toBe(radioItem1.id)
421
+ expect(label2.getAttribute('for')).toBe(radioItem2.id)
422
+ })
423
+
424
+ it('maintains displayName', () => {
425
+ expect(RadioItemWithLabel.displayName).toBe('RadioItemWithLabel')
426
+ })
427
+ })
428
+
429
+ describe('Complex Combinations', () => {
430
+ it('renders complete radio group with all components', () => {
431
+ const onValueChange = jest.fn()
432
+ render(
433
+ <RadioGroup value="option2" onValueChange={onValueChange} data-testid="radio-group">
434
+ <RadioItemWithLabel value="option1" label="Option 1" />
435
+ <RadioItemWithLabel value="option2" label="Option 2" />
436
+ <div className="flex items-center">
437
+ <RadioGroupItem value="option3" />
438
+ <RadioLabel htmlFor="option3">Option 3</RadioLabel>
439
+ </div>
440
+ </RadioGroup>
441
+ )
442
+
443
+ const option1 = screen.getByDisplayValue('option1')
444
+ const option2 = screen.getByDisplayValue('option2')
445
+ const option3 = screen.getByDisplayValue('option3')
446
+
447
+ expect(option1).not.toBeChecked()
448
+ expect(option2).toBeChecked()
449
+ expect(option3).not.toBeChecked()
450
+
451
+ fireEvent.click(option3)
452
+ expect(onValueChange).toHaveBeenCalledWith('option3')
453
+ })
454
+
455
+ it('handles all variants and sizes together', () => {
456
+ render(
457
+ <RadioGroup data-testid="radio-group">
458
+ <RadioGroupItem value="default" variant="default" size="sm" />
459
+ <RadioGroupItem value="outline" variant="outline" size="md" />
460
+ <RadioGroupItem value="filled" variant="filled" size="lg" />
461
+ </RadioGroup>
462
+ )
463
+
464
+ const defaultItem = screen.getByDisplayValue('default').nextElementSibling
465
+ const outlineItem = screen.getByDisplayValue('outline').nextElementSibling
466
+ const filledItem = screen.getByDisplayValue('filled').nextElementSibling
467
+
468
+ expect(defaultItem).toHaveClass('h-3.5', 'w-3.5', 'border-border', 'bg-background')
469
+ expect(outlineItem).toHaveClass('h-5', 'w-5', 'border-border', 'bg-transparent')
470
+ expect(filledItem).toHaveClass('h-6', 'w-6', 'border-primary', 'bg-primary/10')
471
+ })
472
+
473
+ it('handles name attribute for form submission', () => {
474
+ render(
475
+ <RadioGroup name="test-group">
476
+ <RadioGroupItem value="option1" />
477
+ <RadioGroupItem value="option2" />
478
+ </RadioGroup>
479
+ )
480
+
481
+ const option1 = screen.getByDisplayValue('option1')
482
+ const option2 = screen.getByDisplayValue('option2')
483
+
484
+ expect(option1).toHaveAttribute('name', 'test-group')
485
+ expect(option2).toHaveAttribute('name', 'test-group')
486
+ })
487
+ })
488
+
489
+ describe('Edge Cases', () => {
490
+ it('handles empty radio group', () => {
491
+ render(<RadioGroup data-testid="radio-group" />)
492
+
493
+ const radioGroup = screen.getByTestId('radio-group')
494
+ expect(radioGroup).toBeInTheDocument()
495
+ expect(radioGroup).toBeEmptyDOMElement()
496
+ })
497
+
498
+ it('handles radio item without context', () => {
499
+ // RadioGroupItem outside of RadioGroup context
500
+ render(<RadioGroupItem value="test" />)
501
+
502
+ const radioItem = screen.getByDisplayValue('test')
503
+ expect(radioItem).toBeInTheDocument()
504
+ expect(radioItem).not.toBeChecked()
505
+ })
506
+
507
+ it('handles null and undefined children', () => {
508
+ render(
509
+ <RadioGroup>
510
+ {null}
511
+ <RadioGroupItem value="test" />
512
+ {undefined}
513
+ </RadioGroup>
514
+ )
515
+
516
+ const radioItem = screen.getByDisplayValue('test')
517
+ expect(radioItem).toBeInTheDocument()
518
+ })
519
+
520
+ it('handles complex label content', () => {
521
+ render(
522
+ <RadioGroup>
523
+ <RadioItemWithLabel
524
+ value="complex"
525
+ label={
526
+ <div>
527
+ <strong>Complex Label</strong>
528
+ <p>With description</p>
529
+ </div>
530
+ }
531
+ />
532
+ </RadioGroup>
533
+ )
534
+
535
+ expect(screen.getByText('Complex Label')).toBeInTheDocument()
536
+ expect(screen.getByText('With description')).toBeInTheDocument()
537
+ })
538
+
539
+ it('handles disabled radio group with individual enabled items', () => {
540
+ render(
541
+ <RadioGroup disabled>
542
+ <RadioGroupItem value="option1" />
543
+ <RadioGroupItem value="option2" disabled={false} />
544
+ </RadioGroup>
545
+ )
546
+
547
+ const option1 = screen.getByDisplayValue('option1')
548
+ const option2 = screen.getByDisplayValue('option2')
549
+
550
+ // Both should be disabled because group is disabled
551
+ expect(option1).toBeDisabled()
552
+ expect(option2).toBeDisabled()
553
+ })
554
+ })
555
+ })