@12-apps/ui 1.5.0 → 1.5.1

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 +16 -8
  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,964 +0,0 @@
1
- /* eslint-env browser */
2
- import { Box,Button, Typography } from '@mui/material';
3
- import type { Meta, StoryObj } from '@storybook/react-vite';
4
- import React, { useState } from 'react';
5
- import { expect, fireEvent, fn,userEvent, waitFor, within } from 'storybook/test';
6
-
7
- import { Dialog, DialogActions,DialogContent, DialogHeader } from './Dialog';
8
-
9
- const meta: Meta<typeof Dialog> = {
10
- title: 'Feedback/Dialog/Tests',
11
- component: Dialog,
12
- parameters: {
13
- layout: 'centered',
14
- chromatic: { disableSnapshot: false },
15
- docs: {
16
- description: {
17
- component:
18
- 'Comprehensive test suite for the Dialog component covering interactions, accessibility, visual states, performance, and edge cases.',
19
- },
20
- },
21
- },
22
- tags: ['autodocs', 'test', 'component:Dialog'],
23
- };
24
-
25
- export default meta;
26
- type Story = StoryObj<typeof meta>;
27
-
28
- // Test wrapper component
29
- const TestDialogWrapper = ({
30
- children,
31
- onOpen = fn(),
32
- onClose = fn(),
33
- ...args
34
- }: {
35
- children: React.ReactNode;
36
- onOpen?: () => void;
37
- onClose?: () => void;
38
- [key: string]: unknown;
39
- }) => {
40
- const [open, setOpen] = useState(false);
41
-
42
- const handleOpen = () => {
43
- setOpen(true);
44
- onOpen();
45
- };
46
-
47
- const handleClose = () => {
48
- setOpen(false);
49
- onClose();
50
- };
51
-
52
- return (
53
- <Box>
54
- <Button variant="contained" onClick={handleOpen} data-testid="open-dialog-button">
55
- Open Dialog
56
- </Button>
57
- <Dialog {...args} open={open} onClose={handleClose}>
58
- {React.Children.map(children, (child) => {
59
- if (React.isValidElement(child) && child.type === DialogActions) {
60
- // Clone DialogActions and add onClick handlers to buttons
61
- return React.cloneElement(
62
- child,
63
- {},
64
- React.Children.map(child.props.children, (button) => {
65
- if (
66
- React.isValidElement(button) &&
67
- (button.props['data-testid'] === 'cancel-button' ||
68
- button.props['data-testid'] === 'close-modal-button' ||
69
- button.props['data-testid'] === 'force-close-button')
70
- ) {
71
- return React.cloneElement(button, { onClick: handleClose });
72
- }
73
- return button;
74
- }),
75
- );
76
- }
77
- return child;
78
- })}
79
- </Dialog>
80
- </Box>
81
- );
82
- };
83
-
84
- // 1. Basic Interaction Tests
85
- export const BasicInteraction: Story = {
86
- name: '🧪 Basic Interaction Test',
87
- render: (args) => (
88
- <TestDialogWrapper {...args}>
89
- <DialogHeader
90
- title="Basic Interaction Dialog"
91
- subtitle="Test basic user interactions"
92
- data-testid="dialog-header"
93
- />
94
- <DialogContent data-testid="dialog-content">
95
- <Typography>Test content for basic interactions.</Typography>
96
- </DialogContent>
97
- <DialogActions data-testid="dialog-actions">
98
- <Button data-testid="cancel-button">Cancel</Button>
99
- <Button variant="contained" data-testid="confirm-button">
100
- Confirm
101
- </Button>
102
- </DialogActions>
103
- </TestDialogWrapper>
104
- ),
105
- args: {
106
- variant: 'default',
107
- size: 'md',
108
- onOpen: fn(),
109
- onClose: fn(),
110
- },
111
- play: async ({ canvasElement, step, args }) => {
112
- const canvas = within(canvasElement);
113
-
114
- await step('Initial render verification', async () => {
115
- const openButton = canvas.getByTestId('open-dialog-button');
116
- await expect(openButton).toBeInTheDocument();
117
- await expect(openButton).toHaveTextContent('Open Dialog');
118
- });
119
-
120
- await step('Open dialog interaction', async () => {
121
- const openButton = canvas.getByTestId('open-dialog-button');
122
- await userEvent.click(openButton);
123
-
124
- await waitFor(
125
- async () => {
126
- // MUI Dialog renders in a portal outside the component tree
127
- const dialog = document.querySelector('[role="dialog"]');
128
- await expect(dialog).toBeInTheDocument();
129
- },
130
- { timeout: 3000 },
131
- );
132
-
133
- await expect(args.onOpen).toHaveBeenCalledTimes(1);
134
- });
135
-
136
- await step('Dialog content verification', async () => {
137
- // Query within document since dialog is in a portal
138
- const dialogTitle = within(document.body).getByText('Basic Interaction Dialog');
139
- const dialogSubtitle = within(document.body).getByText('Test basic user interactions');
140
- const dialogContent = within(document.body).getByText('Test content for basic interactions.');
141
-
142
- await expect(dialogTitle).toBeInTheDocument();
143
- await expect(dialogSubtitle).toBeInTheDocument();
144
- await expect(dialogContent).toBeInTheDocument();
145
- });
146
-
147
- await step('Close dialog interaction', async () => {
148
- const cancelButton = within(document.body).getByTestId('cancel-button');
149
- await userEvent.click(cancelButton);
150
-
151
- await waitFor(async () => {
152
- const dialog = document.querySelector('[role="dialog"]');
153
- await expect(dialog).not.toBeInTheDocument();
154
- });
155
- });
156
- },
157
- };
158
-
159
- // 2. Keyboard Navigation Test
160
- export const KeyboardNavigation: Story = {
161
- name: '⌨️ Keyboard Navigation Test',
162
- render: (args) => (
163
- <TestDialogWrapper {...args}>
164
- <DialogHeader title="Keyboard Navigation Test" subtitle="Test keyboard accessibility" />
165
- <DialogContent>
166
- <Typography paragraph>Test keyboard navigation and focus management.</Typography>
167
- <Button data-testid="first-focusable">First Button</Button>
168
- <Button data-testid="second-focusable" sx={{ ml: 1 }}>
169
- Second Button
170
- </Button>
171
- </DialogContent>
172
- <DialogActions>
173
- <Button data-testid="cancel-action">Cancel</Button>
174
- <Button variant="contained" data-testid="confirm-action">
175
- Confirm
176
- </Button>
177
- </DialogActions>
178
- </TestDialogWrapper>
179
- ),
180
- args: {
181
- variant: 'default',
182
- size: 'md',
183
- onOpen: fn(),
184
- onClose: fn(),
185
- },
186
- parameters: {
187
- a11y: {
188
- element: '#storybook-root',
189
- config: {
190
- rules: [
191
- { id: 'color-contrast', enabled: true },
192
- { id: 'aria-required-attr', enabled: true },
193
- { id: 'aria-roles', enabled: true },
194
- { id: 'aria-valid-attr-value', enabled: true },
195
- { id: 'button-name', enabled: true },
196
- { id: 'duplicate-id', enabled: true },
197
- { id: 'label', enabled: true },
198
- ],
199
- },
200
- },
201
- },
202
- play: async ({ canvasElement, step }) => {
203
- const canvas = within(canvasElement);
204
-
205
- await step('Open dialog for keyboard testing', async () => {
206
- const openButton = canvas.getByTestId('open-dialog-button');
207
- await userEvent.click(openButton);
208
-
209
- await waitFor(async () => {
210
- const dialog = document.querySelector('[role="dialog"]');
211
- await expect(dialog).toBeInTheDocument();
212
- });
213
- });
214
-
215
- await step('Tab navigation forward', async () => {
216
- // First focusable element should be the first button
217
- const firstButton = within(document.body).getByTestId('first-focusable');
218
- await userEvent.click(firstButton);
219
- await waitFor(() => expect(firstButton).toHaveFocus());
220
-
221
- // Tab to next element
222
- await userEvent.tab();
223
- const secondButton = within(document.body).getByTestId('second-focusable');
224
- await waitFor(() => expect(secondButton).toHaveFocus());
225
-
226
- // Continue tabbing to action buttons
227
- await userEvent.tab();
228
- const cancelButton = within(document.body).getByTestId('cancel-action');
229
- await waitFor(() => expect(cancelButton).toHaveFocus());
230
- });
231
-
232
- await step('Tab navigation backward', async () => {
233
- await userEvent.tab({ shift: true });
234
- const secondButton = within(document.body).getByTestId('second-focusable');
235
- await waitFor(() => expect(secondButton).toHaveFocus());
236
- });
237
-
238
- await step('Escape key handling', async () => {
239
- await userEvent.keyboard('{Escape}');
240
-
241
- await waitFor(async () => {
242
- const dialog = document.querySelector('[role="dialog"]');
243
- await expect(dialog).not.toBeInTheDocument();
244
- });
245
- });
246
- },
247
- };
248
-
249
- // 3. Screen Reader Test
250
- export const ScreenReaderTest: Story = {
251
- name: '🔊 Screen Reader Test',
252
- render: (args) => (
253
- <TestDialogWrapper {...args}>
254
- <DialogHeader
255
- title="Screen Reader Test Dialog"
256
- subtitle="Testing ARIA attributes and labels"
257
- />
258
- <DialogContent>
259
- <Typography>
260
- This dialog tests screen reader compatibility with proper ARIA attributes.
261
- </Typography>
262
- <Typography id="description-text">
263
- Additional description text that should be referenced by aria-describedby.
264
- </Typography>
265
- </DialogContent>
266
- <DialogActions>
267
- <Button aria-label="Cancel dialog">Cancel</Button>
268
- <Button variant="contained" aria-label="Confirm action">
269
- Confirm
270
- </Button>
271
- </DialogActions>
272
- </TestDialogWrapper>
273
- ),
274
- args: {
275
- variant: 'default',
276
- size: 'md',
277
- },
278
- play: async ({ canvasElement, step }) => {
279
- const canvas = within(canvasElement);
280
-
281
- await step('Open dialog for ARIA testing', async () => {
282
- const openButton = canvas.getByTestId('open-dialog-button');
283
- await userEvent.click(openButton);
284
-
285
- await waitFor(async () => {
286
- const dialog = document.querySelector('[role="dialog"]');
287
- await expect(dialog).toBeInTheDocument();
288
- });
289
- });
290
-
291
- await step('Verify dialog role and attributes', async () => {
292
- const dialog = document.querySelector('[role="dialog"]');
293
- await expect(dialog).toBeInTheDocument();
294
- await expect(dialog).toHaveAttribute('role', 'dialog');
295
- });
296
-
297
- await step('Verify ARIA labels on buttons', async () => {
298
- const cancelButton = within(document.body).getByLabelText('Cancel dialog');
299
- const confirmButton = within(document.body).getByLabelText('Confirm action');
300
-
301
- await expect(cancelButton).toBeInTheDocument();
302
- await expect(confirmButton).toBeInTheDocument();
303
- await expect(confirmButton).toHaveAttribute('aria-label', 'Confirm action');
304
- });
305
-
306
- await step('Verify dialog controls accessibility', async () => {
307
- // Verify action buttons have proper ARIA attributes
308
- const cancelButton = within(document.body).getByLabelText('Cancel dialog');
309
- const confirmButton = within(document.body).getByLabelText('Confirm action');
310
- await expect(cancelButton).toBeInTheDocument();
311
- await expect(confirmButton).toBeInTheDocument();
312
- });
313
- },
314
- };
315
-
316
- // 4. Focus Management Test
317
- export const FocusManagement: Story = {
318
- name: '🎯 Focus Management Test',
319
- render: (args) => (
320
- <Box>
321
- <Button data-testid="trigger-button">Trigger Button</Button>
322
- <TestDialogWrapper {...args}>
323
- <DialogHeader title="Focus Management Test" subtitle="Testing focus trap and restoration" />
324
- <DialogContent>
325
- <Button data-testid="first-modal-element">First Element</Button>
326
- <Button data-testid="second-modal-element" sx={{ ml: 1 }}>
327
- Second Element
328
- </Button>
329
- </DialogContent>
330
- <DialogActions>
331
- <Button data-testid="close-modal-button">Close</Button>
332
- </DialogActions>
333
- </TestDialogWrapper>
334
- </Box>
335
- ),
336
- args: {
337
- variant: 'default',
338
- size: 'md',
339
- onOpen: fn(),
340
- onClose: fn(),
341
- },
342
- play: async ({ canvasElement, step }) => {
343
- const canvas = within(canvasElement);
344
-
345
- await step('Focus initial trigger button', async () => {
346
- const triggerButton = canvas.getByTestId('trigger-button');
347
- await userEvent.click(triggerButton);
348
- await waitFor(() => expect(triggerButton).toHaveFocus());
349
- });
350
-
351
- await step('Open modal and verify focus management', async () => {
352
- const openButton = canvas.getByTestId('open-dialog-button');
353
- await userEvent.click(openButton);
354
-
355
- await waitFor(async () => {
356
- const dialog = document.querySelector('[role="dialog"]');
357
- await expect(dialog).toBeInTheDocument();
358
- });
359
-
360
- // Focus should move to the first focusable element in the dialog
361
- // In MUI Dialog, focus typically goes to the dialog container or first interactive element
362
- await waitFor(() => {
363
- const firstElement = within(document.body).getByTestId('first-modal-element');
364
- await userEvent.click(firstElement);
365
- expect(document.activeElement).toBeTruthy();
366
- });
367
- });
368
-
369
- await step('Test focus trap within modal', async () => {
370
- const firstElement = within(document.body).getByTestId('first-modal-element');
371
- const secondElement = within(document.body).getByTestId('second-modal-element');
372
- const closeModalButton = within(document.body).getByTestId('close-modal-button');
373
-
374
- // Focus first element explicitly
375
- await userEvent.click(firstElement);
376
- await waitFor(() => expect(firstElement).toHaveFocus());
377
-
378
- // Tab to next element
379
- await userEvent.tab();
380
- await waitFor(() => expect(secondElement).toHaveFocus());
381
-
382
- // Tab to close button
383
- await userEvent.tab();
384
- await waitFor(() => expect(closeModalButton).toHaveFocus());
385
-
386
- // Tab should cycle back (focus trap) - verify focus is managed
387
- await userEvent.tab();
388
- await waitFor(() => {
389
- const focusedElement = document.activeElement;
390
- expect(focusedElement).toBeTruthy();
391
- // Focus should be on one of the dialog elements
392
- const isInDialog =
393
- focusedElement &&
394
- (focusedElement === firstElement ||
395
- focusedElement === secondElement ||
396
- focusedElement === closeModalButton);
397
- expect(isInDialog).toBe(true);
398
- });
399
- });
400
-
401
- await step('Close modal and verify focus restoration', async () => {
402
- const closeModalButton = within(document.body).getByTestId('close-modal-button');
403
- await userEvent.click(closeModalButton);
404
-
405
- await waitFor(async () => {
406
- const dialog = document.querySelector('[role="dialog"]');
407
- await expect(dialog).not.toBeInTheDocument();
408
- });
409
-
410
- // Focus should return to the open button
411
- const openButton = canvas.getByTestId('open-dialog-button');
412
- await waitFor(() => expect(openButton).toHaveFocus());
413
- });
414
- },
415
- };
416
-
417
- // 5. Visual States Test
418
- export const VisualStates: Story = {
419
- name: '👁️ Visual States Test',
420
- render: (args) => (
421
- <TestDialogWrapper {...args}>
422
- <DialogHeader
423
- title="Visual States Test"
424
- subtitle="Testing different visual states and variants"
425
- />
426
- <DialogContent data-testid="dialog-content">
427
- <Typography>Testing visual states and styling.</Typography>
428
- <Button data-testid="interactive-element">Interactive Element</Button>
429
- </DialogContent>
430
- <DialogActions>
431
- <Button disabled data-testid="disabled-button">
432
- Disabled
433
- </Button>
434
- <Button variant="contained" data-testid="active-button">
435
- Active
436
- </Button>
437
- </DialogActions>
438
- </TestDialogWrapper>
439
- ),
440
- args: {
441
- variant: 'glass',
442
- size: 'md',
443
- glow: true,
444
- gradient: true,
445
- borderRadius: 'lg',
446
- onOpen: fn(),
447
- onClose: fn(),
448
- },
449
- play: async ({ canvasElement, step }) => {
450
- const canvas = within(canvasElement);
451
-
452
- await step('Open dialog for visual testing', async () => {
453
- const openButton = canvas.getByTestId('open-dialog-button');
454
- await userEvent.click(openButton);
455
-
456
- await waitFor(async () => {
457
- const dialog = document.querySelector('[role="dialog"]');
458
- await expect(dialog).toBeInTheDocument();
459
- });
460
- });
461
-
462
- await step('Verify glass variant styling', async () => {
463
- const dialog = document.querySelector('[role="dialog"]');
464
-
465
- // Dialog should have glass morphism styles
466
- await expect(dialog).toBeInTheDocument();
467
- });
468
-
469
- await step('Test hover interactions', async () => {
470
- const interactiveElement = within(document.body).getByTestId('interactive-element');
471
-
472
- await userEvent.hover(interactiveElement);
473
- await expect(interactiveElement).toHaveClass('MuiButton-root');
474
-
475
- await userEvent.unhover(interactiveElement);
476
- });
477
-
478
- await step('Test disabled state', async () => {
479
- const disabledButton = within(document.body).getByTestId('disabled-button');
480
- await expect(disabledButton).toBeDisabled();
481
-
482
- // Verify disabled button has proper styling and cannot receive focus
483
- const computedStyle = window.getComputedStyle(disabledButton);
484
- await expect(computedStyle.pointerEvents).toBe('none');
485
- await expect(disabledButton).toBeDisabled();
486
- });
487
-
488
- await step('Test active button state', async () => {
489
- const activeButton = within(document.body).getByTestId('active-button');
490
- await expect(activeButton).not.toBeDisabled();
491
- await expect(activeButton).toHaveClass('MuiButton-contained');
492
- });
493
- },
494
- };
495
-
496
- // 6. Performance Test
497
- export const PerformanceTest: Story = {
498
- name: '⚡ Performance Test',
499
- render: (args) => {
500
- const items = Array.from({ length: 100 }, (_, i) => ({
501
- id: i,
502
- name: `Item ${i + 1}`,
503
- }));
504
-
505
- return (
506
- <TestDialogWrapper {...args}>
507
- <DialogHeader title="Performance Test Dialog" subtitle="Testing with large content" />
508
- <DialogContent data-testid="performance-content">
509
- <Box sx={{ maxHeight: 400, overflow: 'auto' }} data-testid="scroll-container">
510
- {items.map((item) => (
511
- <Typography key={item.id} data-testid={`item-${item.id}`}>
512
- {item.name}
513
- </Typography>
514
- ))}
515
- </Box>
516
- </DialogContent>
517
- <DialogActions>
518
- <Button>Close</Button>
519
- </DialogActions>
520
- </TestDialogWrapper>
521
- );
522
- },
523
- args: {
524
- variant: 'default',
525
- size: 'lg',
526
- },
527
- play: async ({ canvasElement, step }) => {
528
- const canvas = within(canvasElement);
529
-
530
- await step('Open dialog for performance testing', async () => {
531
- const openButton = canvas.getByTestId('open-dialog-button');
532
-
533
- const startTime = window.performance.now();
534
- await userEvent.click(openButton);
535
-
536
- await waitFor(async () => {
537
- const dialog = document.querySelector('[role="dialog"]');
538
- await expect(dialog).toBeInTheDocument();
539
- });
540
-
541
- const endTime = window.performance.now();
542
- const renderTime = endTime - startTime;
543
-
544
- // console.log(`Dialog open time: ${renderTime}ms`);
545
- // Reasonable render time for dialog open
546
- await expect(renderTime).toBeLessThan(500);
547
- });
548
-
549
- await step('Test scroll performance', async () => {
550
- const scrollContainer = within(document.body).getByTestId('scroll-container');
551
-
552
- // Scrolling is what this step is about, so it has to move the container.
553
- // What it must not do is assert a particular offset, which depends on the
554
- // viewport the story renders in.
555
- // eslint-disable-next-line test-flakiness/no-viewport-dependent -- the subject under test is scrolling itself
556
- scrollContainer.scrollTop = scrollContainer.scrollHeight;
557
- fireEvent.scroll(scrollContainer);
558
-
559
- // Asserted on what is rendered rather than on an offset: the list is not
560
- // virtualised, so scrolling must leave every item mounted.
561
- await waitFor(() => {
562
- expect(within(document.body).getAllByTestId(/item-\d+/).length).toBeGreaterThan(0);
563
- });
564
- });
565
-
566
- await step('Measure item render performance', async () => {
567
- const items = within(document.body).getAllByTestId(/item-\d+/);
568
- await expect(items).toHaveLength(100);
569
-
570
- // All items should be rendered efficiently
571
- const startTime = window.performance.now();
572
- items.forEach((item) => {
573
- expect(item).toBeInTheDocument();
574
- });
575
- const endTime = window.performance.now();
576
-
577
- const measureTime = endTime - startTime;
578
- // console.log(`Item measurement time: ${measureTime}ms`);
579
- await expect(measureTime).toBeLessThan(100);
580
- });
581
- },
582
- };
583
-
584
- // 7. Edge Cases Test
585
- export const EdgeCases: Story = {
586
- name: '🔧 Edge Cases Test',
587
- render: (args) => (
588
- <TestDialogWrapper {...args}>
589
- <DialogHeader
590
- title="Edge Cases Test Dialog with Very Long Title That Should Handle Overflow Gracefully"
591
- subtitle="This is a very long subtitle that tests how the dialog handles overflow content and maintains proper layout and accessibility standards"
592
- showCloseButton={args.showCloseButton}
593
- />
594
- <DialogContent data-testid="edge-case-content">
595
- <Typography data-testid="long-text">
596
- This is a very long piece of text that should test how the dialog handles content overflow
597
- and text wrapping. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
598
- tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
599
- exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
600
- dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
601
- </Typography>
602
- <Box data-testid="empty-state" sx={{ display: 'none' }}>
603
- <Typography>No data available</Typography>
604
- </Box>
605
- </DialogContent>
606
- <DialogActions data-testid="edge-case-actions">
607
- <Button>Very Long Button Text That Tests Overflow</Button>
608
- <Button variant="contained">OK</Button>
609
- </DialogActions>
610
- </TestDialogWrapper>
611
- ),
612
- args: {
613
- variant: 'default',
614
- size: 'md',
615
- showCloseButton: true,
616
- },
617
- play: async ({ canvasElement, step }) => {
618
- const canvas = within(canvasElement);
619
-
620
- await step('Open dialog for edge case testing', async () => {
621
- const openButton = canvas.getByTestId('open-dialog-button');
622
- await userEvent.click(openButton);
623
-
624
- await waitFor(async () => {
625
- const dialog = document.querySelector('[role="dialog"]');
626
- await expect(dialog).toBeInTheDocument();
627
- });
628
- });
629
-
630
- await step('Test long title handling', async () => {
631
- const longTitle = within(document.body).getByText(
632
- /Edge Cases Test Dialog with Very Long Title/,
633
- );
634
- await expect(longTitle).toBeInTheDocument();
635
-
636
- // Title should be visible and not cause layout issues
637
- const titleElement = longTitle.closest('[class*="MuiDialogTitle"]');
638
- if (titleElement) {
639
- const computedStyle = window.getComputedStyle(titleElement);
640
- await expect(computedStyle.overflow).toBeDefined();
641
- }
642
- });
643
-
644
- await step('Test long content text wrapping', async () => {
645
- const longText = within(document.body).getByTestId('long-text');
646
- await expect(longText).toBeInTheDocument();
647
-
648
- const computedStyle = window.getComputedStyle(longText);
649
- // Text should wrap properly - check that it's not 'nowrap'
650
- await expect(computedStyle.wordWrap).not.toBe('nowrap');
651
- await expect(computedStyle.overflowWrap).toBeDefined();
652
- });
653
-
654
- await step('Test dialog responsiveness', async () => {
655
- const dialog = document.querySelector('[role="dialog"]');
656
- const dialogContent = within(document.body).getByTestId('edge-case-content');
657
-
658
- await expect(dialog).toBeInTheDocument();
659
- await expect(dialogContent).toBeInTheDocument();
660
-
661
- // Dialog should maintain proper dimensions
662
- const dialogRect = dialog.getBoundingClientRect();
663
- await expect(dialogRect.width).toBeGreaterThan(0);
664
- await expect(dialogRect.height).toBeGreaterThan(0);
665
- });
666
-
667
- await step('Test button overflow handling', async () => {
668
- const longButton = within(document.body).getByText(
669
- 'Very Long Button Text That Tests Overflow',
670
- );
671
- await expect(longButton).toBeInTheDocument();
672
-
673
- // Button should be clickable despite long text
674
- await userEvent.hover(longButton);
675
- await userEvent.click(longButton);
676
- });
677
- },
678
- };
679
-
680
- // 8. Persistent Dialog Test
681
- export const PersistentDialogTest: Story = {
682
- name: '🔒 Persistent Dialog Test',
683
- render: (args) => (
684
- <TestDialogWrapper {...args}>
685
- <DialogHeader
686
- title="Persistent Dialog"
687
- subtitle="Cannot be closed by backdrop or escape"
688
- showCloseButton={false}
689
- />
690
- <DialogContent>
691
- <Typography>
692
- This dialog is persistent and cannot be closed by clicking the backdrop or pressing the
693
- Escape key. It must be closed using the action buttons.
694
- </Typography>
695
- </DialogContent>
696
- <DialogActions>
697
- <Button color="error" data-testid="force-close-button">
698
- Force Close
699
- </Button>
700
- <Button variant="contained">Confirm</Button>
701
- </DialogActions>
702
- </TestDialogWrapper>
703
- ),
704
- args: {
705
- variant: 'default',
706
- size: 'md',
707
- persistent: true,
708
- backdrop: true,
709
- onOpen: fn(),
710
- onClose: fn(),
711
- },
712
- play: async ({ canvasElement, step }) => {
713
- const canvas = within(canvasElement);
714
-
715
- await step('Open persistent dialog', async () => {
716
- const openButton = canvas.getByTestId('open-dialog-button');
717
- await userEvent.click(openButton);
718
-
719
- await waitFor(async () => {
720
- const dialog = document.querySelector('[role="dialog"]');
721
- await expect(dialog).toBeInTheDocument();
722
- });
723
- });
724
-
725
- await step('Test escape key does not close persistent dialog', async () => {
726
- await userEvent.keyboard('{Escape}');
727
-
728
- // Wait a moment and verify dialog is still open
729
- await new Promise((resolve) => window.setTimeout(resolve, 100));
730
- const dialog = document.querySelector('[role="dialog"]');
731
- await expect(dialog).toBeInTheDocument();
732
- });
733
-
734
- await step('Test backdrop click does not close persistent dialog', async () => {
735
- const backdrop = document.querySelector('.MuiBackdrop-root');
736
- if (backdrop) {
737
- await userEvent.click(backdrop);
738
-
739
- // Wait a moment and verify dialog is still open
740
- await new Promise((resolve) => window.setTimeout(resolve, 100));
741
- const dialog = document.querySelector('[role="dialog"]');
742
- await expect(dialog).toBeInTheDocument();
743
- }
744
- });
745
-
746
- await step('Test dialog cannot be closed by backdrop', async () => {
747
- // The header has to be there for its lack of a close button to mean
748
- // anything — otherwise this passes just as well when the dialog failed to
749
- // render at all.
750
- const dialogHeader = document.querySelector('[class*="MuiDialogTitle"]');
751
- await expect(dialogHeader).toBeInTheDocument();
752
- await expect(dialogHeader?.querySelector('[aria-label="close"]')).toBeNull();
753
- });
754
-
755
- await step('Test dialog can only be closed via action buttons', async () => {
756
- const forceCloseButton = within(document.body).getByTestId('force-close-button');
757
- await userEvent.click(forceCloseButton);
758
-
759
- await waitFor(async () => {
760
- const dialog = document.querySelector('[role="dialog"]');
761
- await expect(dialog).not.toBeInTheDocument();
762
- });
763
- });
764
- },
765
- };
766
-
767
- // 9. Responsive Design Test
768
- export const ResponsiveDesign: Story = {
769
- name: '📱 Responsive Design Test',
770
- render: (args) => (
771
- <TestDialogWrapper {...args}>
772
- <DialogHeader title="Responsive Design Test" subtitle="Testing dialog responsiveness" />
773
- <DialogContent>
774
- <Typography>
775
- This dialog should adapt to different screen sizes and maintain proper layout on mobile,
776
- tablet, and desktop viewports.
777
- </Typography>
778
- </DialogContent>
779
- <DialogActions>
780
- <Button>Cancel</Button>
781
- <Button variant="contained">Confirm</Button>
782
- </DialogActions>
783
- </TestDialogWrapper>
784
- ),
785
- args: {
786
- variant: 'default',
787
- size: 'md',
788
- onOpen: fn(),
789
- onClose: fn(),
790
- },
791
- parameters: {
792
- viewport: {
793
- defaultViewport: 'mobile1',
794
- },
795
- },
796
- play: async ({ canvasElement, step }) => {
797
- const canvas = within(canvasElement);
798
-
799
- await step('Open dialog on mobile viewport', async () => {
800
- const openButton = canvas.getByTestId('open-dialog-button');
801
- await userEvent.click(openButton);
802
-
803
- await waitFor(async () => {
804
- const dialog = document.querySelector('[role="dialog"]');
805
- await expect(dialog).toBeInTheDocument();
806
- });
807
- });
808
-
809
- await step('Test mobile dialog layout', async () => {
810
- const dialog = document.querySelector('[role="dialog"]');
811
- const dialogRect = dialog.getBoundingClientRect();
812
-
813
- // Measured against the body, which is the box the dialog is actually laid
814
- // out in — window.innerWidth includes any scrollbar, so the same dialog
815
- // scores differently depending on whether the page happens to scroll. The
816
- // viewport is fixed for this story by its own `mobile1` parameter above,
817
- // which the rule cannot see from here.
818
- // eslint-disable-next-line test-flakiness/no-viewport-dependent -- viewport pinned by the story's mobile1 parameter
819
- const widthRatio = dialogRect.width / document.body.clientWidth;
820
- await expect(widthRatio).toBeGreaterThan(0.5); // Dialog should take at least 50% of width
821
- });
822
- },
823
- };
824
-
825
- // 10. Theme Variations Test
826
- export const ThemeVariations: Story = {
827
- name: '🎨 Theme Variations Test',
828
- render: (args) => (
829
- <TestDialogWrapper {...args}>
830
- <DialogHeader title="Theme Variations Test" subtitle="Testing dark and light themes" />
831
- <DialogContent>
832
- <Typography>
833
- This dialog should display correctly in both light and dark themes, maintaining proper
834
- contrast and readability.
835
- </Typography>
836
- </DialogContent>
837
- <DialogActions>
838
- <Button>Cancel</Button>
839
- <Button variant="contained">Confirm</Button>
840
- </DialogActions>
841
- </TestDialogWrapper>
842
- ),
843
- args: {
844
- variant: 'default',
845
- size: 'md',
846
- onOpen: fn(),
847
- onClose: fn(),
848
- },
849
- parameters: {
850
- backgrounds: {
851
- default: 'dark',
852
- },
853
- },
854
- play: async ({ canvasElement, step }) => {
855
- const canvas = within(canvasElement);
856
-
857
- await step('Open dialog for theme testing', async () => {
858
- const openButton = canvas.getByTestId('open-dialog-button');
859
- await userEvent.click(openButton);
860
-
861
- await waitFor(async () => {
862
- const dialog = document.querySelector('[role="dialog"]');
863
- await expect(dialog).toBeInTheDocument();
864
- });
865
- });
866
-
867
- await step('Verify theme-aware styling', async () => {
868
- const dialog = document.querySelector('[role="dialog"]');
869
- const computedStyle = window.getComputedStyle(dialog);
870
-
871
- // Dialog should have proper background color
872
- await expect(computedStyle.backgroundColor).toBeDefined();
873
- await expect(computedStyle.color).toBeDefined();
874
- });
875
- },
876
- };
877
-
878
- // 11. Integration Test
879
- export const Integration: Story = {
880
- name: '🔗 Integration Test',
881
- render: (args) => {
882
- const [nestedOpen, setNestedOpen] = useState(false);
883
-
884
- return (
885
- <TestDialogWrapper {...args}>
886
- <DialogHeader title="Integration Test" subtitle="Testing dialog with other components" />
887
- <DialogContent>
888
- <Typography paragraph>
889
- This test verifies dialog integration with other components like nested dialogs, form
890
- elements, and complex interactions.
891
- </Typography>
892
- <Button
893
- variant="outlined"
894
- onClick={() => setNestedOpen(true)}
895
- data-testid="open-nested-dialog"
896
- >
897
- Open Nested Dialog
898
- </Button>
899
- <Dialog open={nestedOpen} onClose={() => setNestedOpen(false)} size="sm">
900
- <DialogHeader title="Nested Dialog" />
901
- <DialogContent>
902
- <Typography>This is a nested dialog for testing integration.</Typography>
903
- </DialogContent>
904
- <DialogActions>
905
- <Button onClick={() => setNestedOpen(false)} data-testid="close-nested-dialog">
906
- Close Nested
907
- </Button>
908
- </DialogActions>
909
- </Dialog>
910
- </DialogContent>
911
- <DialogActions>
912
- <Button>Cancel</Button>
913
- <Button variant="contained">Confirm</Button>
914
- </DialogActions>
915
- </TestDialogWrapper>
916
- );
917
- },
918
- args: {
919
- variant: 'default',
920
- size: 'lg',
921
- onOpen: fn(),
922
- onClose: fn(),
923
- },
924
- play: async ({ canvasElement, step }) => {
925
- const canvas = within(canvasElement);
926
-
927
- await step('Open main dialog', async () => {
928
- const openButton = canvas.getByTestId('open-dialog-button');
929
- await userEvent.click(openButton);
930
-
931
- await waitFor(async () => {
932
- const dialog = document.querySelector('[role="dialog"]');
933
- await expect(dialog).toBeInTheDocument();
934
- });
935
- });
936
-
937
- await step('Test nested dialog functionality', async () => {
938
- const openNestedButton = within(document.body).getByTestId('open-nested-dialog');
939
- await userEvent.click(openNestedButton);
940
-
941
- await waitFor(async () => {
942
- const dialogs = document.querySelectorAll('[role="dialog"]');
943
- await expect(dialogs).toHaveLength(2);
944
- });
945
-
946
- // Close nested dialog
947
- const closeNestedButton = within(document.body).getByTestId('close-nested-dialog');
948
- await userEvent.click(closeNestedButton);
949
-
950
- await waitFor(async () => {
951
- const dialogs = document.querySelectorAll('[role="dialog"]');
952
- await expect(dialogs).toHaveLength(1);
953
- });
954
- });
955
-
956
- await step('Verify main dialog still functional', async () => {
957
- const mainDialog = document.querySelector('[role="dialog"]');
958
- await expect(mainDialog).toBeInTheDocument();
959
-
960
- const dialogTitle = within(document.body).getByText('Integration Test');
961
- await expect(dialogTitle).toBeInTheDocument();
962
- });
963
- },
964
- };