@12-apps/ui 1.5.0 → 1.5.2

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 (229) hide show
  1. package/package.json +17 -9
  2. package/src/button/index.ts +1 -0
  3. package/src/social-login-button/index.ts +1 -0
  4. package/src/{social-login-button.tsx → social-login-button/social-login-button.tsx} +5 -5
  5. package/src/user-avatar/index.ts +1 -0
  6. package/src/{user-avatar.tsx → user-avatar/user-avatar.tsx} +4 -4
  7. package/eslint.config.js +0 -89
  8. package/src/__tests__/data-grid.test.tsx +0 -125
  9. package/src/__tests__/package-wiring.test.ts +0 -41
  10. package/src/__tests__/setup.ts +0 -1
  11. package/src/__tests__/social-login-button.test.tsx +0 -186
  12. package/src/__tests__/user-avatar.test.tsx +0 -195
  13. package/src/__tests__/viewport.test.ts +0 -50
  14. package/src/components/command/__tests__/command.test.tsx +0 -112
  15. package/src/components/data-display/Alert/Alert.stories.tsx +0 -559
  16. package/src/components/data-display/Alert/Alert.test.stories.tsx +0 -707
  17. package/src/components/data-display/AlertDialog/AlertDialog.stories.tsx +0 -362
  18. package/src/components/data-display/AlertDialog/AlertDialog.test.stories.tsx +0 -763
  19. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.stories.tsx +0 -230
  20. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.test.stories.tsx +0 -270
  21. package/src/components/data-display/Avatar/Avatar.stories.tsx +0 -721
  22. package/src/components/data-display/Avatar/Avatar.test.stories.tsx +0 -822
  23. package/src/components/data-display/Badge/Badge.stories.tsx +0 -1134
  24. package/src/components/data-display/Badge/Badge.test.stories.tsx +0 -1194
  25. package/src/components/data-display/Banner/Banner.stories.tsx +0 -528
  26. package/src/components/data-display/Banner/Banner.test.stories.tsx +0 -511
  27. package/src/components/data-display/Carousel/Carousel.stories.tsx +0 -607
  28. package/src/components/data-display/Carousel/Carousel.test.stories.tsx +0 -701
  29. package/src/components/data-display/Chart/Chart.stories.tsx +0 -568
  30. package/src/components/data-display/Chart/Chart.test.stories.tsx +0 -174
  31. package/src/components/data-display/Chart/SpecChart.stories.tsx +0 -150
  32. package/src/components/data-display/Chart/SpecChart.test.stories.tsx +0 -56
  33. package/src/components/data-display/Chart/__tests__/SpecChart.test.tsx +0 -60
  34. package/src/components/data-display/Chart/__tests__/chart-format.test.ts +0 -43
  35. package/src/components/data-display/Chart/__tests__/chart-spec.test.ts +0 -119
  36. package/src/components/data-display/Chip/Chip.stories.tsx +0 -252
  37. package/src/components/data-display/Chip/Chip.test.stories.tsx +0 -266
  38. package/src/components/data-display/DataGrid/DataGrid.stories.tsx +0 -515
  39. package/src/components/data-display/DataGrid/DataGrid.test.stories.tsx +0 -653
  40. package/src/components/data-display/DataViews/__tests__/DataViewsGrid.test.tsx +0 -271
  41. package/src/components/data-display/DataViews/__tests__/DataViewsTableBase.test.tsx +0 -134
  42. package/src/components/data-display/DataViews/__tests__/SaveViewModal.test.tsx +0 -83
  43. package/src/components/data-display/DataViews/__tests__/data-views-filter.test.ts +0 -115
  44. package/src/components/data-display/DataViews/__tests__/data-views-preview.test.ts +0 -53
  45. package/src/components/data-display/DataViews/__tests__/range-pill.test.tsx +0 -114
  46. package/src/components/data-display/DataViews/base-card.stories.tsx +0 -136
  47. package/src/components/data-display/DescriptionItem/DescriptionItem.stories.tsx +0 -254
  48. package/src/components/data-display/EmptyState/EmptyState.stories.tsx +0 -282
  49. package/src/components/data-display/EmptyState/EmptyState.test.stories.tsx +0 -441
  50. package/src/components/data-display/ErrorState/ErrorState.stories.tsx +0 -110
  51. package/src/components/data-display/ErrorState/ErrorState.test.stories.tsx +0 -133
  52. package/src/components/data-display/HoverCard/HoverCard.stories.tsx +0 -650
  53. package/src/components/data-display/HoverCard/HoverCard.test.stories.tsx +0 -929
  54. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.stories.tsx +0 -411
  55. package/src/components/data-display/LazyImage/LazyImage.stories.tsx +0 -387
  56. package/src/components/data-display/Lightbox/Lightbox.stories.tsx +0 -315
  57. package/src/components/data-display/Lightbox/Lightbox.test.stories.tsx +0 -598
  58. package/src/components/data-display/LoadingState/LoadingState.stories.tsx +0 -124
  59. package/src/components/data-display/LoadingState/LoadingState.test.stories.tsx +0 -99
  60. package/src/components/data-display/MapPreview/MapPreview.stories.tsx +0 -458
  61. package/src/components/data-display/MapPreview/MapPreview.test.stories.tsx +0 -394
  62. package/src/components/data-display/Popover/Popover.stories.tsx +0 -295
  63. package/src/components/data-display/Popover/Popover.test.stories.tsx +0 -1162
  64. package/src/components/data-display/Progress/Progress.stories.tsx +0 -481
  65. package/src/components/data-display/Progress/Progress.test.stories.tsx +0 -2070
  66. package/src/components/data-display/SectionOnboarding/SectionOnboarding.stories.tsx +0 -160
  67. package/src/components/data-display/SectionOnboarding/SectionOnboarding.test.stories.tsx +0 -190
  68. package/src/components/data-display/Sheet/Sheet.stories.tsx +0 -883
  69. package/src/components/data-display/Sheet/Sheet.test.stories.tsx +0 -1105
  70. package/src/components/data-display/StatCard/StatCard.stories.tsx +0 -167
  71. package/src/components/data-display/StatCard/StatCard.test.stories.tsx +0 -240
  72. package/src/components/data-display/Stepper/Stepper.stories.tsx +0 -540
  73. package/src/components/data-display/Stepper/Stepper.test.stories.tsx +0 -600
  74. package/src/components/data-display/Table/Table.stories.tsx +0 -803
  75. package/src/components/data-display/Table/Table.test.stories.tsx +0 -369
  76. package/src/components/data-display/Timeline/Timeline.stories.tsx +0 -442
  77. package/src/components/data-display/Timeline/Timeline.test.stories.tsx +0 -930
  78. package/src/components/data-display/TimingDiagram/TimingDiagram.stories.tsx +0 -475
  79. package/src/components/data-display/TimingDiagram/TimingDiagram.test.stories.tsx +0 -734
  80. package/src/components/data-display/Tooltip/Tooltip.stories.tsx +0 -468
  81. package/src/components/data-display/Tooltip/Tooltip.test.stories.tsx +0 -1154
  82. package/src/components/feedback/ConfirmAction/ConfirmAction.stories.tsx +0 -146
  83. package/src/components/feedback/ConfirmAction/ConfirmAction.test.stories.tsx +0 -114
  84. package/src/components/feedback/ConfirmAction/__tests__/confirm-action.test.tsx +0 -288
  85. package/src/components/feedback/Dialog/Dialog.stories.tsx +0 -833
  86. package/src/components/feedback/Dialog/Dialog.test.stories.tsx +0 -964
  87. package/src/components/feedback/Dialog/__tests__/dialog-content-spacing.test.tsx +0 -66
  88. package/src/components/feedback/Modal/Modal.stories.tsx +0 -765
  89. package/src/components/feedback/Modal/Modal.test.stories.tsx +0 -251
  90. package/src/components/feedback/Sonner/Sonner.stories.tsx +0 -698
  91. package/src/components/feedback/Sonner/Sonner.test.stories.tsx +0 -896
  92. package/src/components/feedback/StackedModal/StackedModal.stories.tsx +0 -1783
  93. package/src/components/feedback/StackedModal/StackedModal.test.stories.tsx +0 -973
  94. package/src/components/feedback/StackedModal/__tests__/stacked-modal-viewport.test.tsx +0 -104
  95. package/src/components/feedback/Toast/Toast.stories.tsx +0 -548
  96. package/src/components/feedback/Toast/Toast.test.stories.tsx +0 -834
  97. package/src/components/feedback/TutorialOverlay/TutorialOverlay.stories.tsx +0 -691
  98. package/src/components/feedback/TutorialOverlay/TutorialOverlay.test.stories.tsx +0 -634
  99. package/src/components/form/AddressAutocomplete/AddressAutocomplete.stories.tsx +0 -665
  100. package/src/components/form/AddressAutocomplete/AddressAutocomplete.test.stories.tsx +0 -727
  101. package/src/components/form/Autocomplete/Autocomplete.stories.tsx +0 -715
  102. package/src/components/form/Autocomplete/Autocomplete.test.stories.tsx +0 -825
  103. package/src/components/form/Button/Button.stories.tsx +0 -365
  104. package/src/components/form/Button/Button.test.stories.tsx +0 -607
  105. package/src/components/form/Calendar/Calendar.stories.tsx +0 -349
  106. package/src/components/form/Calendar/Calendar.test.stories.tsx +0 -464
  107. package/src/components/form/CepField/CepField.stories.tsx +0 -138
  108. package/src/components/form/CepField/CepField.test.stories.tsx +0 -281
  109. package/src/components/form/Checkbox/Checkbox.stories.tsx +0 -265
  110. package/src/components/form/Checkbox/Checkbox.test.stories.tsx +0 -181
  111. package/src/components/form/CodeEditor/CodeEditor.stories.tsx +0 -871
  112. package/src/components/form/CodeEditor/CodeEditor.test.stories.tsx +0 -574
  113. package/src/components/form/Command/Command.stories.tsx +0 -580
  114. package/src/components/form/Command/Command.test.stories.tsx +0 -215
  115. package/src/components/form/CreatableSelect/CreatableSelect.stories.tsx +0 -112
  116. package/src/components/form/CreatableSelect/CreatableSelect.test.stories.tsx +0 -134
  117. package/src/components/form/Form/Form.stories.tsx +0 -687
  118. package/src/components/form/Form/Form.test.stories.tsx +0 -601
  119. package/src/components/form/Input/Input.stories.tsx +0 -260
  120. package/src/components/form/Input/Input.test.stories.tsx +0 -1191
  121. package/src/components/form/InputOTP/InputOTP.stories.tsx +0 -774
  122. package/src/components/form/InputOTP/InputOTP.test.stories.tsx +0 -588
  123. package/src/components/form/Label/Label.stories.tsx +0 -473
  124. package/src/components/form/Label/Label.test.stories.tsx +0 -915
  125. package/src/components/form/Menubar/Menubar.stories.tsx +0 -472
  126. package/src/components/form/Menubar/Menubar.test.stories.tsx +0 -584
  127. package/src/components/form/PasswordStrength/PasswordStrength.stories.tsx +0 -562
  128. package/src/components/form/PasswordStrength/PasswordStrength.test.stories.tsx +0 -327
  129. package/src/components/form/PhoneInput/PhoneInput.stories.tsx +0 -495
  130. package/src/components/form/PhoneInput/PhoneInput.test.stories.tsx +0 -666
  131. package/src/components/form/RadioGroup/RadioGroup.stories.tsx +0 -518
  132. package/src/components/form/RadioGroup/RadioGroup.test.stories.tsx +0 -685
  133. package/src/components/form/RichTextEditor/RichTextEditor.stories.tsx +0 -261
  134. package/src/components/form/RichTextEditor/RichTextEditor.test.stories.tsx +0 -491
  135. package/src/components/form/SearchPalette/SearchPalette.stories.tsx +0 -135
  136. package/src/components/form/Select/Select.stories.tsx +0 -364
  137. package/src/components/form/Select/Select.test.stories.tsx +0 -985
  138. package/src/components/form/Slider/Slider.stories.tsx +0 -418
  139. package/src/components/form/Slider/Slider.test.stories.tsx +0 -1042
  140. package/src/components/form/Switch/Switch.stories.tsx +0 -697
  141. package/src/components/form/Switch/Switch.test.stories.tsx +0 -597
  142. package/src/components/form/Textarea/Textarea.stories.tsx +0 -473
  143. package/src/components/form/Textarea/Textarea.test.stories.tsx +0 -702
  144. package/src/components/form/Toggle/Toggle.stories.tsx +0 -638
  145. package/src/components/form/Toggle/Toggle.test.stories.tsx +0 -1159
  146. package/src/components/form/ToggleGroup/ToggleGroup.stories.tsx +0 -617
  147. package/src/components/form/ToggleGroup/ToggleGroup.test.stories.tsx +0 -915
  148. package/src/components/form/UploadButton/UploadButton.stories.tsx +0 -367
  149. package/src/components/form/UploadButton/UploadButton.test.stories.tsx +0 -573
  150. package/src/components/form/total-form/total-form.test.tsx +0 -214
  151. package/src/components/layout/Accordion/Accordion.stories.tsx +0 -694
  152. package/src/components/layout/Accordion/Accordion.test.stories.tsx +0 -1344
  153. package/src/components/layout/Card/Card.stories.tsx +0 -591
  154. package/src/components/layout/Card/Card.test.stories.tsx +0 -1134
  155. package/src/components/layout/CardGrid/__tests__/CardGrid.test.tsx +0 -92
  156. package/src/components/layout/Collapsible/Collapsible.stories.tsx +0 -180
  157. package/src/components/layout/Collapsible/Collapsible.test.stories.tsx +0 -308
  158. package/src/components/layout/Container/Container.stories.tsx +0 -557
  159. package/src/components/layout/Container/Container.test.stories.tsx +0 -745
  160. package/src/components/layout/ContentToolbar/ContentToolbar.stories.tsx +0 -129
  161. package/src/components/layout/ContentToolbar/ContentToolbar.test.stories.tsx +0 -251
  162. package/src/components/layout/ContentToolbar/__tests__/ColumnsMenu.test.tsx +0 -39
  163. package/src/components/layout/ContentToolbar/__tests__/MultiSelectDropdown.test.tsx +0 -131
  164. package/src/components/layout/ContentToolbar/__tests__/SavedViewsMenu.test.tsx +0 -99
  165. package/src/components/layout/Dashboard/Dashboard.stories.tsx +0 -104
  166. package/src/components/layout/Dashboard/Dashboard.test.stories.tsx +0 -190
  167. package/src/components/layout/Drawer/Drawer.stories.tsx +0 -658
  168. package/src/components/layout/Drawer/Drawer.test.stories.tsx +0 -1343
  169. package/src/components/layout/Resizable/Resizable.stories.tsx +0 -1039
  170. package/src/components/layout/Resizable/Resizable.test.stories.tsx +0 -754
  171. package/src/components/layout/ScrollArea/ScrollArea.stories.tsx +0 -651
  172. package/src/components/layout/ScrollArea/ScrollArea.test.stories.tsx +0 -619
  173. package/src/components/layout/Separator/Separator.stories.tsx +0 -563
  174. package/src/components/layout/Separator/Separator.test.stories.tsx +0 -518
  175. package/src/components/layout/SettingsLayout/SettingsLayout.stories.tsx +0 -192
  176. package/src/components/layout/SettingsLayout/SettingsLayout.test.stories.tsx +0 -175
  177. package/src/components/layout/Sidebar/Sidebar.stories.tsx +0 -609
  178. package/src/components/layout/Sidebar/Sidebar.test.stories.tsx +0 -1324
  179. package/src/components/layout/Skeleton/Skeleton.stories.tsx +0 -689
  180. package/src/components/layout/Skeleton/Skeleton.test.stories.tsx +0 -521
  181. package/src/components/layout/Spacer/Spacer.stories.tsx +0 -502
  182. package/src/components/layout/Spacer/Spacer.test.stories.tsx +0 -474
  183. package/src/components/layout/TableFilter/TableFilter.stories.tsx +0 -82
  184. package/src/components/layout/TableFilter/TableFilter.test.stories.tsx +0 -87
  185. package/src/components/navigation/Breadcrumbs/Breadcrumbs.stories.tsx +0 -638
  186. package/src/components/navigation/Breadcrumbs/Breadcrumbs.test.stories.tsx +0 -1008
  187. package/src/components/navigation/CommandPalette/CommandPalette.stories.tsx +0 -386
  188. package/src/components/navigation/CommandPalette/CommandPalette.test.stories.tsx +0 -435
  189. package/src/components/navigation/ContextMenu/ContextMenu.stories.tsx +0 -614
  190. package/src/components/navigation/ContextMenu/ContextMenu.test.stories.tsx +0 -845
  191. package/src/components/navigation/DropdownMenu/DropdownMenu.stories.tsx +0 -578
  192. package/src/components/navigation/DropdownMenu/DropdownMenu.test.stories.tsx +0 -660
  193. package/src/components/navigation/NavigationMenu/stories/NavigationMenu.stories.tsx +0 -516
  194. package/src/components/navigation/NavigationMenu/stories/NavigationMenu.test.stories.tsx +0 -935
  195. package/src/components/navigation/NavigationMenu/stories/NavigationMenuHorizontal.stories.tsx +0 -501
  196. package/src/components/navigation/NavigationMenu/stories/NavigationMenuVertical.stories.tsx +0 -453
  197. package/src/components/navigation/Pagination/Pagination.stories.tsx +0 -602
  198. package/src/components/navigation/Pagination/Pagination.test.stories.tsx +0 -520
  199. package/src/components/navigation/Tabs/Tabs.stories.tsx +0 -1004
  200. package/src/components/navigation/Tabs/Tabs.test.stories.tsx +0 -1225
  201. package/src/components/typography/Blockquote/Blockquote.stories.tsx +0 -359
  202. package/src/components/typography/Blockquote/Blockquote.test.stories.tsx +0 -432
  203. package/src/components/typography/Code/Code.stories.tsx +0 -686
  204. package/src/components/typography/Code/Code.test.stories.tsx +0 -703
  205. package/src/components/typography/Heading/Heading.stories.tsx +0 -451
  206. package/src/components/typography/Heading/Heading.test.stories.tsx +0 -830
  207. package/src/components/typography/Paragraph/Paragraph.stories.tsx +0 -280
  208. package/src/components/typography/Paragraph/Paragraph.test.stories.tsx +0 -231
  209. package/src/components/typography/Text/Text.stories.tsx +0 -359
  210. package/src/components/typography/Text/Text.test.stories.tsx +0 -759
  211. package/src/components/utility/AnimatedIcon/AnimatedIcon.stories.tsx +0 -945
  212. package/src/components/utility/AnimatedIcon/AnimatedIcon.test.stories.tsx +0 -603
  213. package/src/components/utility/AspectRatio/AspectRatio.stories.tsx +0 -414
  214. package/src/components/utility/AspectRatio/AspectRatio.test.stories.tsx +0 -859
  215. package/src/components/utility/InfiniteScroll/InfiniteScroll.stories.tsx +0 -620
  216. package/src/components/utility/InfiniteScroll/InfiniteScroll.test.stories.tsx +0 -361
  217. package/src/components/utility/InstallPrompt/InstallPrompt.stories.tsx +0 -118
  218. package/src/components/utility/InstallPrompt/InstallPrompt.test.stories.tsx +0 -83
  219. package/src/components/utility/InstallPrompt/__tests__/InstallPrompt.ios.test.tsx +0 -65
  220. package/src/components/utility/InstallPrompt/__tests__/usePwaInstall.test.tsx +0 -271
  221. package/src/components/utility/Portal/Portal.stories.tsx +0 -340
  222. package/src/components/utility/Portal/Portal.test.stories.tsx +0 -2086
  223. package/src/components/utility/Transition/Transition.stories.tsx +0 -493
  224. package/src/components/utility/Transition/Transition.test.stories.tsx +0 -854
  225. package/src/components/utility/VirtualList/VirtualList.stories.tsx +0 -1073
  226. package/src/components/utility/VirtualList/VirtualList.test.stories.tsx +0 -1085
  227. package/src/components/utility/WorkflowStep/WorkflowStep.stories.tsx +0 -431
  228. package/src/components/utility/WorkflowStep/WorkflowStep.test.stories.tsx +0 -364
  229. /package/src/{button.tsx → button/button.tsx} +0 -0
@@ -1,896 +0,0 @@
1
- import { Box,Button, Stack, TextField } from '@mui/material';
2
- import type { Meta, StoryObj } from '@storybook/react-vite';
3
- import React from 'react';
4
- import { expect, userEvent, waitFor,within } from 'storybook/test';
5
-
6
- import { SonnerProvider, useSonner } from './Sonner';
7
-
8
- const meta: Meta<typeof SonnerProvider> = {
9
- title: 'Feedback/Sonner/Tests',
10
- component: SonnerProvider,
11
- parameters: {
12
- layout: 'padded',
13
- docs: {
14
- description: {
15
- component: 'Comprehensive test stories for Sonner toast component',
16
- },
17
- },
18
- },
19
- tags: ['autodocs', 'test', 'component:Sonner'],
20
- };
21
-
22
- export default meta;
23
- type Story = StoryObj<typeof meta>;
24
-
25
- // Test wrapper component with toast functionality
26
- const TestWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (
27
- <SonnerProvider>{children}</SonnerProvider>
28
- );
29
-
30
- // Basic interaction test component
31
- const BasicInteractionTest: React.FC = () => {
32
- const { toast, success, error, warning, info, loading, dismiss } = useSonner();
33
-
34
- return (
35
- <Stack spacing={2} data-testid="basic-interaction">
36
- <Button data-testid="basic-toast-btn" onClick={() => toast('Basic toast message')}>
37
- Basic Toast
38
- </Button>
39
- <Button data-testid="success-toast-btn" onClick={() => success('Success message')}>
40
- Success Toast
41
- </Button>
42
- <Button data-testid="error-toast-btn" onClick={() => error('Error message')}>
43
- Error Toast
44
- </Button>
45
- <Button data-testid="warning-toast-btn" onClick={() => warning('Warning message')}>
46
- Warning Toast
47
- </Button>
48
- <Button data-testid="info-toast-btn" onClick={() => info('Info message')}>
49
- Info Toast
50
- </Button>
51
- <Button data-testid="loading-toast-btn" onClick={() => loading('Loading...')}>
52
- Loading Toast
53
- </Button>
54
- <Button data-testid="dismiss-all-btn" onClick={() => dismiss()}>
55
- Dismiss All
56
- </Button>
57
- </Stack>
58
- );
59
- };
60
-
61
- // Form interaction test component
62
- const FormInteractionTest: React.FC = () => {
63
- const { success, error } = useSonner();
64
- const [value, setValue] = React.useState('');
65
-
66
- const handleSubmit = () => {
67
- if (value.trim()) {
68
- success('Form submitted successfully!');
69
- setValue('');
70
- } else {
71
- error('Please enter a value');
72
- }
73
- };
74
-
75
- return (
76
- <Box data-testid="form-interaction">
77
- <Stack spacing={2}>
78
- <TextField
79
- data-testid="form-input"
80
- value={value}
81
- onChange={(e) => setValue(e.target.value)}
82
- placeholder="Enter some text"
83
- onKeyDown={(e) => e.key === 'Enter' && handleSubmit()}
84
- />
85
- <Button data-testid="submit-btn" onClick={handleSubmit}>
86
- Submit
87
- </Button>
88
- </Stack>
89
- </Box>
90
- );
91
- };
92
-
93
- // Keyboard navigation test component
94
- const KeyboardNavigationTest: React.FC = () => {
95
- const { toast, dismiss } = useSonner();
96
-
97
- React.useEffect(() => {
98
- const handleKeyDown = (e: globalThis.KeyboardEvent) => {
99
- if (e.key === 't' && e.ctrlKey) {
100
- e.preventDefault();
101
- toast('Triggered by Ctrl+T');
102
- }
103
- if (e.key === 'Escape') {
104
- dismiss();
105
- }
106
- };
107
-
108
- window.addEventListener('keydown', handleKeyDown);
109
- return () => window.removeEventListener('keydown', handleKeyDown);
110
- }, [toast, dismiss]);
111
-
112
- return (
113
- <Box data-testid="keyboard-navigation">
114
- <Stack spacing={2}>
115
- <Button data-testid="show-toast-btn" onClick={() => toast('Toast for keyboard test')}>
116
- Show Toast
117
- </Button>
118
- <p>Press Ctrl+T to show toast, Esc to dismiss</p>
119
- </Stack>
120
- </Box>
121
- );
122
- };
123
-
124
- // Screen reader test component
125
- const ScreenReaderTest: React.FC = () => {
126
- const { toast } = useSonner();
127
-
128
- return (
129
- <Box data-testid="screen-reader">
130
- <Button
131
- data-testid="accessible-toast-btn"
132
- onClick={() => toast('Screen reader accessible toast')}
133
- aria-label="Show accessible toast notification"
134
- >
135
- Accessible Toast
136
- </Button>
137
- </Box>
138
- );
139
- };
140
-
141
- // Focus management test component
142
- const FocusManagementTest: React.FC = () => {
143
- const { toast } = useSonner();
144
- const buttonRef = React.useRef<HTMLButtonElement>(null);
145
-
146
- const handleToast = () => {
147
- toast('Focus management test', {
148
- action: {
149
- label: 'Focus Button',
150
- onClick: () => {
151
- buttonRef.current?.focus();
152
- },
153
- },
154
- });
155
- };
156
-
157
- return (
158
- <Box data-testid="focus-management">
159
- <Stack spacing={2}>
160
- <Button data-testid="focus-toast-btn" onClick={handleToast}>
161
- Show Toast with Action
162
- </Button>
163
- <Button ref={buttonRef} data-testid="focus-target-btn">
164
- Focus Target
165
- </Button>
166
- </Stack>
167
- </Box>
168
- );
169
- };
170
-
171
- // Responsive design test component
172
- const ResponsiveDesignTest: React.FC = () => {
173
- const { toast } = useSonner();
174
-
175
- return (
176
- <Box data-testid="responsive-design">
177
- <Button
178
- data-testid="responsive-toast-btn"
179
- onClick={() => toast('Responsive design test message that is quite long to test wrapping')}
180
- >
181
- Test Responsive Toast
182
- </Button>
183
- </Box>
184
- );
185
- };
186
-
187
- // Theme variations test component
188
- const ThemeVariationsTest: React.FC = () => {
189
- const { toast } = useSonner();
190
-
191
- return (
192
- <Box data-testid="theme-variations">
193
- <Stack spacing={2}>
194
- <Button
195
- data-testid="default-theme-btn"
196
- onClick={() => toast('Default theme toast', { variant: 'default' })}
197
- >
198
- Default Theme
199
- </Button>
200
- <Button
201
- data-testid="glass-theme-btn"
202
- onClick={() => toast('Glass theme toast', { variant: 'glass' })}
203
- >
204
- Glass Theme
205
- </Button>
206
- <Button
207
- data-testid="minimal-theme-btn"
208
- onClick={() => toast('Minimal theme toast', { variant: 'minimal' })}
209
- >
210
- Minimal Theme
211
- </Button>
212
- </Stack>
213
- </Box>
214
- );
215
- };
216
-
217
- // Visual states test component
218
- const VisualStatesTest: React.FC = () => {
219
- const { toast, success, error } = useSonner();
220
-
221
- return (
222
- <Box data-testid="visual-states">
223
- <Stack spacing={2}>
224
- <Button
225
- data-testid="persistent-toast-btn"
226
- onClick={() => toast('Persistent toast', { persistent: true })}
227
- >
228
- Persistent Toast
229
- </Button>
230
- <Button
231
- data-testid="important-toast-btn"
232
- onClick={() => success('Important success', { important: true })}
233
- >
234
- Important Success
235
- </Button>
236
- <Button
237
- data-testid="with-description-btn"
238
- onClick={() =>
239
- error('Error with description', {
240
- description: 'This is a detailed description of the error',
241
- })
242
- }
243
- >
244
- With Description
245
- </Button>
246
- </Stack>
247
- </Box>
248
- );
249
- };
250
-
251
- // Performance test component
252
- const PerformanceTest: React.FC = () => {
253
- const { toast, dismiss } = useSonner();
254
-
255
- const handleManyToasts = () => {
256
- const startTime = Date.now();
257
- for (let i = 0; i < 10; i++) {
258
- toast(`Toast ${i + 1}`);
259
- }
260
- const endTime = Date.now();
261
- window.setTimeout(() => {
262
- toast(`Created 10 toasts in ${endTime - startTime}ms`);
263
- }, 100);
264
- };
265
-
266
- return (
267
- <Box data-testid="performance">
268
- <Stack spacing={2}>
269
- <Button data-testid="many-toasts-btn" onClick={handleManyToasts}>
270
- Create Many Toasts
271
- </Button>
272
- <Button data-testid="clear-toasts-btn" onClick={() => dismiss()}>
273
- Clear All
274
- </Button>
275
- </Stack>
276
- </Box>
277
- );
278
- };
279
-
280
- // Edge cases test component
281
- const EdgeCasesTest: React.FC = () => {
282
- const { toast, promise } = useSonner();
283
-
284
- const handleEmptyToast = () => {
285
- toast('');
286
- };
287
-
288
- const handleLongToast = () => {
289
- toast(
290
- 'This is a very long toast message that should test how the component handles extensive text content that might overflow or wrap to multiple lines in the toast notification container',
291
- );
292
- };
293
-
294
- const handlePromiseToast = () => {
295
- const testPromise = new Promise((resolve) => {
296
- window.setTimeout(() => resolve('Success!'), 2000);
297
- });
298
-
299
- promise(testPromise, {
300
- loading: 'Processing...',
301
- success: 'Promise resolved!',
302
- error: 'Promise failed!',
303
- });
304
- };
305
-
306
- return (
307
- <Box data-testid="edge-cases">
308
- <Stack spacing={2}>
309
- <Button data-testid="empty-toast-btn" onClick={handleEmptyToast}>
310
- Empty Toast
311
- </Button>
312
- <Button data-testid="long-toast-btn" onClick={handleLongToast}>
313
- Long Message
314
- </Button>
315
- <Button data-testid="promise-toast-btn" onClick={handlePromiseToast}>
316
- Promise Toast
317
- </Button>
318
- </Stack>
319
- </Box>
320
- );
321
- };
322
-
323
- // Integration test component
324
- const IntegrationTest: React.FC = () => {
325
- const { toast, success, error, dismiss } = useSonner();
326
- const [step, setStep] = React.useState(0);
327
-
328
- const runIntegrationTest = async () => {
329
- setStep(1);
330
- toast('Step 1: Starting integration test');
331
-
332
- window.setTimeout(() => {
333
- setStep(2);
334
- success('Step 2: First action completed');
335
- }, 1000);
336
-
337
- window.setTimeout(() => {
338
- setStep(3);
339
- error('Step 3: Simulated error occurred');
340
- }, 2000);
341
-
342
- window.setTimeout(() => {
343
- setStep(4);
344
- dismiss();
345
- success('Step 4: Integration test completed');
346
- setStep(0);
347
- }, 3000);
348
- };
349
-
350
- return (
351
- <Box data-testid="integration">
352
- <Stack spacing={2}>
353
- <Button data-testid="integration-test-btn" onClick={runIntegrationTest} disabled={step > 0}>
354
- Run Integration Test {step > 0 && `(Step ${step}/4)`}
355
- </Button>
356
- </Stack>
357
- </Box>
358
- );
359
- };
360
-
361
- // Test stories
362
- export const BasicInteraction: Story = {
363
- render: () => (
364
- <TestWrapper>
365
- <BasicInteractionTest />
366
- </TestWrapper>
367
- ),
368
- play: async ({ canvasElement, step }) => {
369
- const canvas = within(canvasElement.ownerDocument.body);
370
- const localCanvas = within(canvasElement);
371
-
372
- await step('Test basic toast', async () => {
373
- const basicBtn = localCanvas.getByTestId('basic-toast-btn');
374
- await userEvent.click(basicBtn);
375
-
376
- // Verify toast appears in the DOM
377
- await waitFor(() => {
378
- expect(canvas.getByText('Basic toast message')).toBeInTheDocument();
379
- });
380
- });
381
-
382
- await step('Test success toast with icon', async () => {
383
- const successBtn = localCanvas.getByTestId('success-toast-btn');
384
- await userEvent.click(successBtn);
385
-
386
- await waitFor(() => {
387
- expect(canvas.getByText('Success message')).toBeInTheDocument();
388
- // Check for success icon (CheckCircle)
389
- const toasts = canvas.getAllByText(/Success message|Basic toast message/);
390
- expect(toasts.length).toBeGreaterThan(0);
391
- });
392
- });
393
-
394
- await step('Test error toast', async () => {
395
- const errorBtn = localCanvas.getByTestId('error-toast-btn');
396
- await userEvent.click(errorBtn);
397
-
398
- await waitFor(() => {
399
- expect(canvas.getByText('Error message')).toBeInTheDocument();
400
- });
401
- });
402
-
403
- await step('Test dismiss all functionality', async () => {
404
- const dismissBtn = localCanvas.getByTestId('dismiss-all-btn');
405
- await userEvent.click(dismissBtn);
406
-
407
- // Wait for toasts to disappear with animation
408
- await waitFor(
409
- () => {
410
- expect(canvas.queryByText('Basic toast message')).not.toBeInTheDocument();
411
- expect(canvas.queryByText('Success message')).not.toBeInTheDocument();
412
- expect(canvas.queryByText('Error message')).not.toBeInTheDocument();
413
- },
414
- { timeout: 2000 },
415
- );
416
- });
417
- },
418
- };
419
-
420
- export const FormInteraction: Story = {
421
- render: () => (
422
- <TestWrapper>
423
- <FormInteractionTest />
424
- </TestWrapper>
425
- ),
426
- play: async ({ canvasElement, step }) => {
427
- const canvas = within(canvasElement.ownerDocument.body);
428
- const localCanvas = within(canvasElement);
429
-
430
- const submitBtn = localCanvas.getByTestId('submit-btn');
431
-
432
- await step('Test empty submission - should show error toast', async () => {
433
- await userEvent.click(submitBtn);
434
-
435
- await waitFor(() => {
436
- expect(canvas.getByText('Please enter a value')).toBeInTheDocument();
437
- });
438
-
439
- // Wait a bit for the error toast to be visible
440
- await new Promise((resolve) => window.setTimeout(resolve, 500));
441
- });
442
-
443
- await step('Test valid submission - should show success toast', async () => {
444
- // Find the actual MUI input element inside the TextField
445
- const inputField = localCanvas.getByTestId('form-input');
446
- const actualInput = inputField.querySelector('input');
447
- expect(actualInput).not.toBeNull();
448
-
449
- // Type directly in the input element
450
- await userEvent.type(actualInput!, 'Test input');
451
-
452
- // Wait for the form to be ready and submit
453
- await new Promise(resolve => window.setTimeout(resolve, 100));
454
- await userEvent.click(submitBtn);
455
-
456
- // Check that success toast appears
457
- await waitFor(() => {
458
- expect(canvas.getByText('Form submitted successfully!')).toBeInTheDocument();
459
- }, { timeout: 2000 });
460
-
461
- // Verify input was cleared after successful submission
462
- await waitFor(() => {
463
- if (actualInput) {
464
- expect(actualInput.value).toBe('');
465
- }
466
- });
467
- });
468
- },
469
- };
470
-
471
- export const KeyboardNavigation: Story = {
472
- render: () => (
473
- <TestWrapper>
474
- <KeyboardNavigationTest />
475
- </TestWrapper>
476
- ),
477
- play: async ({ canvasElement, step }) => {
478
- const canvas = within(canvasElement.ownerDocument.body);
479
- const localCanvas = within(canvasElement);
480
-
481
- await step('Show toast and verify keyboard navigation', async () => {
482
- const showBtn = localCanvas.getByTestId('show-toast-btn');
483
- await userEvent.click(showBtn);
484
-
485
- // Verify toast appears
486
- await waitFor(() => {
487
- expect(canvas.getByText('Toast for keyboard test')).toBeInTheDocument();
488
- });
489
-
490
- // Test Escape key dismissal
491
- await userEvent.keyboard('{Escape}');
492
-
493
- // Verify toast is dismissed
494
- await waitFor(
495
- () => {
496
- expect(canvas.queryByText('Toast for keyboard test')).not.toBeInTheDocument();
497
- },
498
- { timeout: 1000 },
499
- );
500
- });
501
- },
502
- };
503
-
504
- export const ScreenReader: Story = {
505
- render: () => (
506
- <TestWrapper>
507
- <ScreenReaderTest />
508
- </TestWrapper>
509
- ),
510
- play: async ({ canvasElement, step }) => {
511
- const canvas = within(canvasElement.ownerDocument.body);
512
- const localCanvas = within(canvasElement);
513
-
514
- await step('Verify accessibility attributes and screen reader support', async () => {
515
- const accessibleBtn = localCanvas.getByTestId('accessible-toast-btn');
516
- expect(accessibleBtn).toHaveAttribute('aria-label', 'Show accessible toast notification');
517
-
518
- await userEvent.click(accessibleBtn);
519
-
520
- // Verify toast appears with proper ARIA attributes
521
- await waitFor(() => {
522
- const toast = canvas.getByText('Screen reader accessible toast');
523
- expect(toast).toBeInTheDocument();
524
- // Toast container should have proper role for screen readers
525
- const toastContainer = toast.closest('[role="status"], [role="alert"]');
526
- expect(toastContainer || toast.parentElement).toBeInTheDocument();
527
- });
528
- });
529
- },
530
- };
531
-
532
- export const FocusManagement: Story = {
533
- render: () => (
534
- <TestWrapper>
535
- <FocusManagementTest />
536
- </TestWrapper>
537
- ),
538
- play: async ({ canvasElement, step }) => {
539
- const canvas = within(canvasElement.ownerDocument.body);
540
- const localCanvas = within(canvasElement);
541
-
542
- await step('Test focus management with action buttons', async () => {
543
- const focusBtn = localCanvas.getByTestId('focus-toast-btn');
544
- const targetBtn = localCanvas.getByTestId('focus-target-btn');
545
-
546
- await userEvent.click(focusBtn);
547
-
548
- // Verify toast appears with action button
549
- await waitFor(() => {
550
- expect(canvas.getByText('Focus management test')).toBeInTheDocument();
551
- expect(canvas.getByText('Focus Button')).toBeInTheDocument();
552
- });
553
-
554
- // Click the action button in the toast
555
- const actionBtn = canvas.getByText('Focus Button');
556
- await userEvent.click(actionBtn);
557
-
558
- // Verify focus moved to target button
559
- await waitFor(() => {
560
- expect(targetBtn).toHaveFocus();
561
- });
562
- });
563
- },
564
- };
565
-
566
- export const ResponsiveDesign: Story = {
567
- render: () => (
568
- <TestWrapper>
569
- <ResponsiveDesignTest />
570
- </TestWrapper>
571
- ),
572
- parameters: {
573
- viewport: { defaultViewport: 'mobile1' },
574
- },
575
- play: async ({ canvasElement, step }) => {
576
- const canvas = within(canvasElement.ownerDocument.body);
577
- const localCanvas = within(canvasElement);
578
-
579
- await step('Test responsive design and text wrapping', async () => {
580
- const responsiveBtn = localCanvas.getByTestId('responsive-toast-btn');
581
- await userEvent.click(responsiveBtn);
582
-
583
- // Verify long text wraps properly
584
- await waitFor(() => {
585
- const toast = canvas.getByText(
586
- 'Responsive design test message that is quite long to test wrapping',
587
- );
588
- expect(toast).toBeInTheDocument();
589
-
590
- // Check toast has max width constraint
591
- const toastContainer = toast.closest('[class*="MuiBox"]');
592
- if (toastContainer) {
593
- const styles = window.getComputedStyle(toastContainer);
594
- const maxWidth = styles.maxWidth;
595
- if (maxWidth && maxWidth !== 'none') {
596
- const parsedWidth = parseInt(maxWidth);
597
- if (!isNaN(parsedWidth)) {
598
- expect(parsedWidth).toBeLessThanOrEqual(400);
599
- }
600
- }
601
- }
602
- });
603
- });
604
- },
605
- };
606
-
607
- export const ThemeVariations: Story = {
608
- render: () => (
609
- <TestWrapper>
610
- <ThemeVariationsTest />
611
- </TestWrapper>
612
- ),
613
- play: async ({ canvasElement, step }) => {
614
- const canvas = within(canvasElement.ownerDocument.body);
615
- const localCanvas = within(canvasElement);
616
-
617
- await step('Test default theme', async () => {
618
- const defaultBtn = localCanvas.getByTestId('default-theme-btn');
619
- await userEvent.click(defaultBtn);
620
-
621
- await waitFor(() => {
622
- expect(canvas.getByText('Default theme toast')).toBeInTheDocument();
623
- });
624
- });
625
-
626
- await step('Test glass theme with backdrop filter', async () => {
627
- const glassBtn = localCanvas.getByTestId('glass-theme-btn');
628
- await userEvent.click(glassBtn);
629
-
630
- await waitFor(() => {
631
- const glassToast = canvas.getByText('Glass theme toast');
632
- expect(glassToast).toBeInTheDocument();
633
- // Glass effect should have backdrop filter - check parent container with role
634
- const toastContainer = glassToast.closest('[role="status"], [role="alert"]');
635
- expect(toastContainer).toBeInTheDocument();
636
-
637
- if (toastContainer) {
638
- const styles = window.getComputedStyle(toastContainer);
639
- const backdropFilter = styles.backdropFilter || (styles as CSSStyleDeclaration & Record<string, string>).webkitBackdropFilter;
640
-
641
- // Glass variant should have glass characteristics - check multiple possible indicators
642
- const hasBlur = backdropFilter && backdropFilter !== 'none' && backdropFilter.includes('blur');
643
- const hasTransparentBg = styles.backgroundColor && (styles.backgroundColor.includes('rgba') ||
644
- parseFloat(styles.opacity || '1') < 1);
645
- const hasGlassBorder = styles.border && styles.border.includes('rgba');
646
-
647
- // At least one glass effect should be present
648
- const hasGlassEffect = hasBlur || hasTransparentBg || hasGlassBorder;
649
- expect(hasGlassEffect).toBeTruthy();
650
- }
651
- });
652
- });
653
-
654
- await step('Test minimal theme and toast stacking', async () => {
655
- const minimalBtn = localCanvas.getByTestId('minimal-theme-btn');
656
- await userEvent.click(minimalBtn);
657
-
658
- await waitFor(() => {
659
- const minimalToast = canvas.getByText('Minimal theme toast');
660
- expect(minimalToast).toBeInTheDocument();
661
- });
662
-
663
- // Verify multiple toasts are stacked
664
- await waitFor(() => {
665
- const allToasts = canvas.getAllByText(/theme toast/);
666
- expect(allToasts.length).toBeGreaterThanOrEqual(3);
667
- });
668
- });
669
- },
670
- };
671
-
672
- export const VisualStates: Story = {
673
- render: () => (
674
- <TestWrapper>
675
- <VisualStatesTest />
676
- </TestWrapper>
677
- ),
678
- play: async ({ canvasElement, step }) => {
679
- const canvas = within(canvasElement.ownerDocument.body);
680
- const localCanvas = within(canvasElement);
681
-
682
- await step('Test persistent toast', async () => {
683
- const persistentBtn = localCanvas.getByTestId('persistent-toast-btn');
684
- await userEvent.click(persistentBtn);
685
-
686
- await waitFor(() => {
687
- expect(canvas.getByText('Persistent toast')).toBeInTheDocument();
688
- });
689
- });
690
-
691
- await step('Test important toast styling', async () => {
692
- const importantBtn = localCanvas.getByTestId('important-toast-btn');
693
- await userEvent.click(importantBtn);
694
-
695
- await waitFor(() => {
696
- const importantToast = canvas.getByText('Important success');
697
- expect(importantToast).toBeInTheDocument();
698
- const styles = window.getComputedStyle(importantToast);
699
- expect(parseInt(styles.fontWeight)).toBeGreaterThanOrEqual(600);
700
- });
701
- });
702
-
703
- await step('Test toast with description', async () => {
704
- const descriptionBtn = localCanvas.getByTestId('with-description-btn');
705
- await userEvent.click(descriptionBtn);
706
-
707
- await waitFor(() => {
708
- expect(canvas.getByText('Error with description')).toBeInTheDocument();
709
- expect(canvas.getByText('This is a detailed description of the error')).toBeInTheDocument();
710
- });
711
- });
712
-
713
- await step('Verify persistent toast remains visible', async () => {
714
- // Wait to verify persistent toast is still there after 2 seconds (reduced from 5 seconds)
715
- await new Promise((resolve) => window.setTimeout(resolve, 2000));
716
- expect(canvas.getByText('Persistent toast')).toBeInTheDocument();
717
- });
718
- },
719
- };
720
-
721
- export const Performance: Story = {
722
- render: () => (
723
- <TestWrapper>
724
- <PerformanceTest />
725
- </TestWrapper>
726
- ),
727
- play: async ({ canvasElement, step }) => {
728
- const canvas = within(canvasElement.ownerDocument.body);
729
- const localCanvas = within(canvasElement);
730
-
731
- await step('Test performance with many toasts', async () => {
732
- const manyToastsBtn = localCanvas.getByTestId('many-toasts-btn');
733
- await userEvent.click(manyToastsBtn);
734
-
735
- // Verify multiple toasts are created - check for any toast content
736
- await waitFor(() => {
737
- // Check for any of the created toasts (may be limited by max visible toasts)
738
- const toastElements = canvasElement.ownerDocument.querySelectorAll('[role="status"], [role="alert"]');
739
- expect(toastElements.length).toBeGreaterThan(0);
740
- });
741
-
742
- // Look for some of the toast messages that should exist
743
- await waitFor(() => {
744
- const hasToast1 = canvas.queryByText('Toast 1');
745
- const hasToast10 = canvas.queryByText('Toast 10');
746
- const hasToast5 = canvas.queryByText('Toast 5');
747
- // At least one of the toasts should be visible
748
- expect(hasToast1 || hasToast5 || hasToast10).toBeTruthy();
749
- });
750
-
751
- // Verify performance message appears (this is created after a timeout)
752
- await waitFor(() => {
753
- const perfMessage = canvas.queryByText(/Created 10 toasts in \d+ms/);
754
- expect(perfMessage).toBeTruthy();
755
- }, { timeout: 1000 });
756
- });
757
-
758
- await step('Clear all toasts and verify cleanup', async () => {
759
- const clearBtn = localCanvas.getByTestId('clear-toasts-btn');
760
- await userEvent.click(clearBtn);
761
-
762
- // Verify all toasts are dismissed
763
- await waitFor(
764
- () => {
765
- expect(canvas.queryByText('Toast 1')).not.toBeInTheDocument();
766
- expect(canvas.queryByText('Toast 10')).not.toBeInTheDocument();
767
- },
768
- { timeout: 2000 },
769
- );
770
- });
771
- },
772
- };
773
-
774
- export const EdgeCases: Story = {
775
- render: () => (
776
- <TestWrapper>
777
- <EdgeCasesTest />
778
- </TestWrapper>
779
- ),
780
- play: async ({ canvasElement, step }) => {
781
- const canvas = within(canvasElement.ownerDocument.body);
782
- const localCanvas = within(canvasElement);
783
-
784
- await step('Test empty toast', async () => {
785
- const emptyBtn = localCanvas.getByTestId('empty-toast-btn');
786
- await userEvent.click(emptyBtn);
787
-
788
- // Empty toast might not have text, check for toast container presence
789
- await waitFor(() => {
790
- // Check if any toast containers exist by looking for elements with Collapse class
791
- const toastElements = canvasElement.ownerDocument.querySelectorAll('[class*="Collapse"]');
792
- expect(toastElements.length).toBeGreaterThan(0);
793
- });
794
- });
795
-
796
- await step('Test long message toast', async () => {
797
- const longBtn = localCanvas.getByTestId('long-toast-btn');
798
- await userEvent.click(longBtn);
799
-
800
- await waitFor(() => {
801
- const longToast = canvas.getByText(/This is a very long toast message/);
802
- expect(longToast).toBeInTheDocument();
803
- // Verify toast has proper text wrapping constraints
804
- const toastContainer = longToast.closest('[role="status"], [role="alert"]');
805
- if (toastContainer) {
806
- const styles = window.getComputedStyle(toastContainer);
807
- // Check that container has max width constraint for proper wrapping
808
- const maxWidth = styles.maxWidth;
809
- expect(maxWidth).toBeTruthy();
810
- expect(maxWidth).not.toBe('none');
811
- }
812
- });
813
- });
814
-
815
- await step('Test promise toast lifecycle', async () => {
816
- const promiseBtn = localCanvas.getByTestId('promise-toast-btn');
817
- await userEvent.click(promiseBtn);
818
-
819
- // First, loading toast should appear
820
- await waitFor(() => {
821
- expect(canvas.getByText('Processing...')).toBeInTheDocument();
822
- });
823
-
824
- // After 2 seconds, success toast should replace loading
825
- await waitFor(
826
- () => {
827
- expect(canvas.queryByText('Processing...')).not.toBeInTheDocument();
828
- expect(canvas.getByText('Promise resolved!')).toBeInTheDocument();
829
- },
830
- { timeout: 3000 },
831
- );
832
- });
833
- },
834
- };
835
-
836
- export const Integration: Story = {
837
- render: () => (
838
- <TestWrapper>
839
- <IntegrationTest />
840
- </TestWrapper>
841
- ),
842
- play: async ({ canvasElement, step }) => {
843
- const canvas = within(canvasElement.ownerDocument.body);
844
- const localCanvas = within(canvasElement);
845
-
846
- await step('Run multi-step integration test', async () => {
847
- const integrationBtn = localCanvas.getByTestId('integration-test-btn');
848
- await userEvent.click(integrationBtn);
849
-
850
- // Step 1: Starting toast
851
- await waitFor(() => {
852
- expect(canvas.getByText('Step 1: Starting integration test')).toBeInTheDocument();
853
- expect(integrationBtn).toHaveTextContent('Run Integration Test (Step 1/4)');
854
- });
855
-
856
- // Step 2: Success toast
857
- await waitFor(
858
- () => {
859
- expect(canvas.getByText('Step 2: First action completed')).toBeInTheDocument();
860
- expect(integrationBtn).toHaveTextContent('Run Integration Test (Step 2/4)');
861
- },
862
- { timeout: 2000 },
863
- );
864
-
865
- // Step 3: Error toast
866
- await waitFor(
867
- () => {
868
- expect(canvas.getByText('Step 3: Simulated error occurred')).toBeInTheDocument();
869
- expect(integrationBtn).toHaveTextContent('Run Integration Test (Step 3/4)');
870
- },
871
- { timeout: 3000 },
872
- );
873
-
874
- // Step 4: Completion - wait longer for all steps to complete
875
- await waitFor(
876
- () => {
877
- // Button should be re-enabled after completion
878
- expect(integrationBtn).not.toBeDisabled();
879
- expect(integrationBtn).toHaveTextContent('Run Integration Test');
880
- },
881
- { timeout: 5000 },
882
- );
883
-
884
- // Check that final completion toast appeared (might be transient)
885
- await waitFor(
886
- () => {
887
- const completionToast = canvas.queryByText('Step 4: Integration test completed');
888
- // Test passes if either the toast is visible or the test has completed (button re-enabled)
889
- const testCompleted = !integrationBtn.disabled && integrationBtn.textContent === 'Run Integration Test';
890
- expect(completionToast || testCompleted).toBeTruthy();
891
- },
892
- { timeout: 1000 },
893
- );
894
- });
895
- },
896
- };