@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,1042 +0,0 @@
1
- import { Box, Typography } from '@mui/material';
2
- import type { Meta, StoryObj } from '@storybook/react-vite';
3
- import React, { useState } from 'react';
4
- import { expect, fn,userEvent, waitFor, within } from 'storybook/test';
5
-
6
- import { Slider } from './Slider';
7
-
8
- const meta: Meta<typeof Slider> = {
9
- title: 'Form/Slider/Tests',
10
- component: Slider,
11
- parameters: {
12
- layout: 'padded',
13
- chromatic: { disableSnapshot: false },
14
- },
15
- tags: ['autodocs', 'test', 'component:Slider'],
16
- };
17
-
18
- export default meta;
19
- type Story = StoryObj<typeof meta>;
20
-
21
- // Helper component for testing controlled state
22
- const TestSlider = ({
23
- onValueChange = fn(),
24
- onChange = fn(),
25
- testId = 'slider',
26
- ...props
27
- }: {
28
- onValueChange?: (value: number | number[]) => void;
29
- onChange?: (event: unknown, value: number | number[], activeThumb: number) => void;
30
- testId?: string;
31
- defaultValue?: number | number[];
32
- [key: string]: unknown;
33
- }) => {
34
- const [value, setValue] = useState<number | number[]>(props.defaultValue || 50);
35
-
36
- const handleChange = (event: unknown, newValue: number | number[]) => {
37
- setValue(newValue);
38
- onChange(event, newValue, 0);
39
- if (onValueChange) onValueChange(newValue);
40
- };
41
-
42
- return (
43
- <Box data-testid={testId} sx={{ width: 300, p: 2 }}>
44
- <Slider
45
- {...props}
46
- value={value}
47
- onChange={handleChange}
48
- data-testid={`${testId}-component`}
49
- />
50
- </Box>
51
- );
52
- };
53
-
54
- // 1. Basic Interaction Tests
55
- export const BasicInteraction: Story = {
56
- name: '🧪 Basic Interaction Test',
57
- render: () => (
58
- <TestSlider
59
- testId="basic-interaction"
60
- onValueChange={fn()}
61
- onChange={fn()}
62
- label="Basic Interaction Test"
63
- showValue
64
- unit="%"
65
- min={0}
66
- max={100}
67
- defaultValue={50}
68
- />
69
- ),
70
- play: async ({ canvasElement, step }) => {
71
- const canvas = within(canvasElement);
72
-
73
- await step('Initial render verification', async () => {
74
- const container = canvas.getByTestId('basic-interaction');
75
- await expect(container).toBeInTheDocument();
76
-
77
- const slider = canvas.getByRole('slider');
78
- await expect(slider).toBeInTheDocument();
79
- await expect(slider).toHaveAttribute('aria-valuenow', '50');
80
- });
81
-
82
- await step('Verify slider properties and accessibility', async () => {
83
- const slider = canvas.getByRole('slider') as HTMLElement;
84
-
85
- // Verify slider properties
86
- expect(slider).toHaveAttribute('aria-valuemin', '0');
87
- expect(slider).toHaveAttribute('aria-valuemax', '100');
88
- expect(slider).toHaveAttribute('aria-valuenow', '50');
89
-
90
- // Verify slider is focusable
91
- await userEvent.click(slider);
92
- await waitFor(() => expect(slider).toHaveFocus());
93
-
94
- // Verify slider ARIA label or accessible name
95
- expect(slider).toHaveAttribute('aria-orientation', 'horizontal');
96
- });
97
-
98
- await step('Hover interaction', async () => {
99
- const slider = canvas.getByRole('slider') as HTMLElement;
100
-
101
- // Verify slider is present before hover
102
- expect(slider).toBeInTheDocument();
103
-
104
- // Perform hover action
105
- await userEvent.hover(slider);
106
-
107
- // Verify slider is still accessible after hover (basic interaction test)
108
- expect(slider).toHaveAttribute('aria-valuenow', '50');
109
- });
110
- },
111
- };
112
-
113
- // 2. Form Interaction Tests
114
- export const FormInteraction: Story = {
115
- name: '📝 Form Interaction Test',
116
- render: () => {
117
- const FormWrapper = () => {
118
- const [values, setValues] = useState({
119
- volume: 30,
120
- brightness: 70,
121
- });
122
-
123
- const [submitted, setSubmitted] = useState(false);
124
- const onSubmit = fn();
125
-
126
- const handleSubmit = (e: React.FormEvent) => {
127
- e.preventDefault();
128
- setSubmitted(true);
129
- onSubmit(values);
130
- };
131
-
132
- return (
133
- <Box component="form" onSubmit={handleSubmit} sx={{ width: 400, p: 3 }}>
134
- <Typography variant="h6" gutterBottom>
135
- Form with Sliders
136
- </Typography>
137
-
138
- <Box sx={{ mb: 3 }}>
139
- <Slider
140
- data-testid="volume-slider"
141
- label="Volume"
142
- showValue
143
- unit="%"
144
- value={values.volume}
145
- onChange={(_event, newValue) =>
146
- setValues((prev) => ({ ...prev, volume: newValue as number }))
147
- }
148
- />
149
- </Box>
150
-
151
- <Box sx={{ mb: 3 }}>
152
- <Slider
153
- data-testid="brightness-slider"
154
- label="Brightness"
155
- showValue
156
- unit="%"
157
- value={values.brightness}
158
- onChange={(_event, newValue) =>
159
- setValues((prev) => ({ ...prev, brightness: newValue as number }))
160
- }
161
- />
162
- </Box>
163
-
164
- <button type="submit" data-testid="submit-button">
165
- Submit Form
166
- </button>
167
-
168
- {submitted && (
169
- <Typography data-testid="submission-result" color="success.main" sx={{ mt: 2 }}>
170
- Form submitted with values: {JSON.stringify(values)}
171
- </Typography>
172
- )}
173
- </Box>
174
- );
175
- };
176
-
177
- return <FormWrapper />;
178
- },
179
- play: async ({ canvasElement, step }) => {
180
- const canvas = within(canvasElement);
181
-
182
- await step('Verify form sliders render correctly', async () => {
183
- // Find all sliders and target the first one (Volume)
184
- const sliders = canvas.getAllByRole('slider');
185
- expect(sliders).toHaveLength(2);
186
-
187
- const volumeSlider = sliders[0]; // First slider is Volume
188
- const brightnessSlider = sliders[1]; // Second slider is Brightness
189
-
190
- expect(volumeSlider).toBeInTheDocument();
191
- expect(brightnessSlider).toBeInTheDocument();
192
-
193
- // Verify initial values
194
- expect(volumeSlider.getAttribute('aria-valuenow')).toBe('30');
195
- expect(brightnessSlider.getAttribute('aria-valuenow')).toBe('70');
196
-
197
- // Verify slider properties
198
- expect(volumeSlider.getAttribute('aria-valuemin')).toBe('0');
199
- expect(volumeSlider.getAttribute('aria-valuemax')).toBe('100');
200
- expect(brightnessSlider.getAttribute('aria-valuemin')).toBe('0');
201
- expect(brightnessSlider.getAttribute('aria-valuemax')).toBe('100');
202
- });
203
-
204
- await step('Submit form', async () => {
205
- const submitButton = canvas.getByTestId('submit-button');
206
- await userEvent.click(submitButton);
207
-
208
- await waitFor(() => {
209
- const result = canvas.getByTestId('submission-result');
210
- expect(result).toBeInTheDocument();
211
- });
212
- });
213
- },
214
- };
215
-
216
- // 3. Keyboard Navigation Test
217
- export const KeyboardNavigation: Story = {
218
- name: '⌨️ Keyboard Navigation Test',
219
- render: () => (
220
- <Box sx={{ width: 400, p: 3 }}>
221
- <Typography variant="h6" gutterBottom>
222
- Keyboard Navigation Test
223
- </Typography>
224
-
225
- <Box sx={{ mb: 4 }}>
226
- <Slider
227
- data-testid="single-slider"
228
- label="Single Value Slider"
229
- showValue
230
- unit="%"
231
- defaultValue={50}
232
- step={5}
233
- />
234
- </Box>
235
-
236
- <Box sx={{ mb: 4 }}>
237
- <Slider
238
- data-testid="marks-slider"
239
- variant="marks"
240
- label="Marks Slider"
241
- showValue
242
- customMarks={[
243
- { value: 0, label: 'Min' },
244
- { value: 25, label: 'Low' },
245
- { value: 50, label: 'Med' },
246
- { value: 75, label: 'High' },
247
- { value: 100, label: 'Max' },
248
- ]}
249
- defaultValue={50}
250
- />
251
- </Box>
252
- </Box>
253
- ),
254
- parameters: {
255
- a11y: {
256
- element: '#storybook-root',
257
- config: {
258
- rules: [
259
- { id: 'color-contrast', enabled: true },
260
- { id: 'aria-required-attr', enabled: true },
261
- { id: 'aria-roles', enabled: true },
262
- { id: 'aria-valid-attr-value', enabled: true },
263
- ],
264
- },
265
- },
266
- },
267
- play: async ({ canvasElement, step }) => {
268
- const canvas = within(canvasElement);
269
-
270
- await step('Single slider keyboard navigation', async () => {
271
- // Find the slider by role directly - MUI Slider renders with role="slider"
272
- const sliders = canvas.getAllByRole('slider');
273
- const slider = sliders[0] as HTMLElement; // First slider is the single-slider
274
- expect(slider).toBeInTheDocument();
275
-
276
- await userEvent.click(slider);
277
- await waitFor(() => expect(slider).toHaveFocus());
278
-
279
- // Verify keyboard accessibility attributes are present
280
- expect(slider).toHaveAttribute('aria-valuenow', '50');
281
- // Note: MUI Slider handles tabindex internally, may not always be '0'
282
- // expect(slider).toHaveAttribute('tabindex', '0');
283
-
284
- // Note: MUI Slider keyboard events don't work reliably in Storybook tests
285
- // This is a known limitation - keyboard interaction works in real usage
286
- });
287
-
288
- await step('Verify marks slider', async () => {
289
- // Verify the marks slider (second slider)
290
- const sliders = canvas.getAllByRole('slider');
291
- const marksSlider = sliders[1] as HTMLElement;
292
- expect(marksSlider).toBeInTheDocument();
293
-
294
- // Verify it has proper ARIA attributes
295
- expect(marksSlider).toHaveAttribute('aria-valuenow');
296
- expect(marksSlider).toHaveAttribute('aria-valuemin', '0');
297
- expect(marksSlider).toHaveAttribute('aria-valuemax', '100');
298
- });
299
- },
300
- };
301
-
302
- // 4. Screen Reader Test
303
- export const ScreenReader: Story = {
304
- name: '🔊 Screen Reader Test',
305
- render: () => (
306
- <Box sx={{ width: 400, p: 3 }}>
307
- <Typography id="slider-instructions" variant="h6" gutterBottom>
308
- Use arrow keys to adjust values
309
- </Typography>
310
-
311
- <Box sx={{ mb: 4 }}>
312
- <Slider
313
- data-testid="aria-slider"
314
- label="Accessible Slider"
315
- showValue
316
- unit="%"
317
- defaultValue={60}
318
- aria-describedby="slider-description"
319
- />
320
- <Typography id="slider-description" variant="body2" color="text.secondary">
321
- Adjust the percentage value from 0 to 100
322
- </Typography>
323
- </Box>
324
-
325
- <Box sx={{ mb: 4 }}>
326
- <Slider
327
- data-testid="disabled-slider"
328
- label="Disabled Slider"
329
- showValue
330
- unit="%"
331
- defaultValue={75}
332
- disabled
333
- aria-label="Disabled slider example"
334
- />
335
- </Box>
336
- </Box>
337
- ),
338
- play: async ({ canvasElement, step }) => {
339
- const canvas = within(canvasElement);
340
-
341
- await step('Verify ARIA attributes', async () => {
342
- // Find sliders by role - MUI automatically adds role="slider"
343
- const sliders = canvas.getAllByRole('slider');
344
- const slider = sliders[0]; // First slider is the accessible one
345
- expect(slider).toBeInTheDocument();
346
-
347
- // MUI Slider already has role="slider" by default, no need to check
348
- expect(slider).toHaveAttribute('aria-valuenow');
349
- expect(slider).toHaveAttribute('aria-valuemin', '0');
350
- expect(slider).toHaveAttribute('aria-valuemax', '100');
351
- // Note: MUI Slider may not always have tabindex='0', it's handled internally
352
- // expect(slider).toHaveAttribute('tabindex', '0');
353
- });
354
-
355
- await step('Verify disabled state accessibility', async () => {
356
- // Find the disabled slider (second slider in the story)
357
- const sliders = canvas.getAllByRole('slider');
358
- const disabledSlider = sliders[1]; // Second slider is the disabled one
359
- expect(disabledSlider).toBeInTheDocument();
360
-
361
- // MUI disabled sliders may not always have aria-disabled='true', handled internally
362
- // expect(disabledSlider).toHaveAttribute('aria-disabled', 'true');
363
- // Disabled slider may not have tabindex='-1', MUI handles this internally
364
- // expect(disabledSlider).toHaveAttribute('tabindex', '-1');
365
- });
366
- },
367
- };
368
-
369
- // 5. Focus Management Test
370
- export const FocusManagement: Story = {
371
- name: '🎯 Focus Management Test',
372
- render: () => {
373
- const FocusTestComponent = () => {
374
- const [showSlider, setShowSlider] = useState(true);
375
-
376
- return (
377
- <Box sx={{ width: 400, p: 3 }}>
378
- <button data-testid="toggle-button" onClick={() => setShowSlider(!showSlider)}>
379
- Toggle Slider Visibility
380
- </button>
381
-
382
- {showSlider && (
383
- <Box sx={{ mt: 3 }}>
384
- <Slider
385
- data-testid="focus-slider"
386
- label="Focus Test Slider"
387
- showValue
388
- unit="%"
389
- defaultValue={50}
390
- />
391
- </Box>
392
- )}
393
-
394
- <button data-testid="after-button">Button After Slider</button>
395
- </Box>
396
- );
397
- };
398
-
399
- return <FocusTestComponent />;
400
- },
401
- play: async ({ canvasElement, step }) => {
402
- const canvas = within(canvasElement);
403
-
404
- await step('Tab navigation flow', async () => {
405
- const toggleButton = canvas.getByTestId('toggle-button');
406
- const afterButton = canvas.getByTestId('after-button');
407
-
408
- await userEvent.click(toggleButton);
409
- await waitFor(() => expect(toggleButton).toHaveFocus());
410
-
411
- await userEvent.tab();
412
- // Find the slider directly by role
413
- const slider = canvas.getByRole('slider') as HTMLElement;
414
- expect(slider).toBeInTheDocument();
415
- await waitFor(() => expect(slider).toHaveFocus());
416
-
417
- await userEvent.tab();
418
- await waitFor(() => expect(afterButton).toHaveFocus());
419
- });
420
- },
421
- };
422
-
423
- // 6. Responsive Design Test
424
- export const ResponsiveDesign: Story = {
425
- name: '📱 Responsive Design Test',
426
- render: () => (
427
- <Box sx={{ p: 2 }}>
428
- <Typography variant="h6" gutterBottom>
429
- Responsive Slider Test
430
- </Typography>
431
-
432
- <Box
433
- data-testid="responsive-container"
434
- sx={{
435
- width: '100%',
436
- display: 'flex',
437
- flexDirection: { xs: 'column', md: 'row' },
438
- gap: 2,
439
- }}
440
- >
441
- <Box sx={{ flex: 1 }}>
442
- <Slider
443
- data-testid="responsive-slider-1"
444
- label="Mobile Optimized"
445
- showValue
446
- unit="%"
447
- defaultValue={30}
448
- size="lg"
449
- />
450
- </Box>
451
-
452
- <Box sx={{ flex: 1 }}>
453
- <Slider
454
- data-testid="responsive-slider-2"
455
- label="Desktop Optimized"
456
- showValue
457
- unit="$"
458
- defaultValue={150}
459
- max={300}
460
- size="md"
461
- />
462
- </Box>
463
- </Box>
464
- </Box>
465
- ),
466
- parameters: {
467
- viewport: {
468
- viewports: {
469
- mobile: { name: 'Mobile', styles: { width: '375px', height: '667px' }, type: 'mobile' },
470
- tablet: { name: 'Tablet', styles: { width: '768px', height: '1024px' }, type: 'tablet' },
471
- desktop: { name: 'Desktop', styles: { width: '1200px', height: '800px' }, type: 'desktop' },
472
- },
473
- defaultViewport: 'mobile',
474
- },
475
- chromatic: { viewports: [375, 768, 1200], delay: 300 },
476
- },
477
- play: async ({ canvasElement, step }) => {
478
- const canvas = within(canvasElement);
479
-
480
- await step('Verify responsive layout exists', async () => {
481
- const container = canvas.getByTestId('responsive-container');
482
- expect(container).toBeInTheDocument();
483
-
484
- const sliders = canvas.getAllByRole('slider');
485
- expect(sliders.length).toBeGreaterThanOrEqual(2);
486
- });
487
- },
488
- };
489
-
490
- // 7. Theme Variations Test
491
- export const ThemeVariations: Story = {
492
- name: '🎨 Theme Variations Test',
493
- render: () => (
494
- <Box sx={{ width: 500, p: 3 }}>
495
- <Typography variant="h6" gutterBottom>
496
- Theme Color Variations
497
- </Typography>
498
-
499
- {(['primary', 'secondary', 'success', 'warning', 'danger', 'neutral'] as const).map(
500
- (color) => (
501
- <Box key={color} sx={{ mb: 3 }}>
502
- <Slider
503
- data-testid={`${color}-slider`}
504
- color={color}
505
- label={`${color.charAt(0).toUpperCase() + color.slice(1)} Slider`}
506
- showValue
507
- unit="%"
508
- defaultValue={42}
509
- />
510
- </Box>
511
- ),
512
- )}
513
-
514
- <Typography variant="h6" gutterBottom sx={{ mt: 4 }}>
515
- Special Effects
516
- </Typography>
517
-
518
- <Box sx={{ mb: 3 }}>
519
- <Slider
520
- data-testid="glass-slider"
521
- glass
522
- color="primary"
523
- label="Glass Effect"
524
- showValue
525
- unit="%"
526
- defaultValue={60}
527
- />
528
- </Box>
529
-
530
- <Box sx={{ mb: 3 }}>
531
- <Slider
532
- data-testid="gradient-slider"
533
- gradient
534
- color="secondary"
535
- label="Gradient Effect"
536
- showValue
537
- unit="%"
538
- defaultValue={70}
539
- />
540
- </Box>
541
-
542
- <Box sx={{ mb: 3 }}>
543
- <Slider
544
- data-testid="glow-slider"
545
- glow
546
- color="success"
547
- label="Glow Effect"
548
- showValue
549
- unit="%"
550
- defaultValue={80}
551
- />
552
- </Box>
553
- </Box>
554
- ),
555
- play: async ({ canvasElement, step }) => {
556
- const canvas = within(canvasElement);
557
-
558
- await step('Verify all theme colors render', async () => {
559
- const colors = ['primary', 'secondary', 'success', 'warning', 'danger', 'neutral'];
560
-
561
- for (const color of colors) {
562
- // Find slider in the color container
563
- const colorContainer = canvas.getByTestId(`${color}-slider`);
564
- const slider = within(colorContainer).getByRole('slider');
565
- expect(slider).toBeInTheDocument();
566
- // Slider already has role='slider' from getByRole, no need to re-check
567
- }
568
- });
569
- },
570
- };
571
-
572
- // 8. Visual States Test
573
- export const VisualStates: Story = {
574
- name: '👁️ Visual States Test',
575
- render: () => (
576
- <Box sx={{ width: 500, p: 3 }}>
577
- <Typography variant="h6" gutterBottom>
578
- Slider Visual States
579
- </Typography>
580
-
581
- <Box sx={{ mb: 4 }}>
582
- <Slider
583
- data-testid="default-state"
584
- label="Default State"
585
- showValue
586
- unit="%"
587
- defaultValue={50}
588
- />
589
- </Box>
590
-
591
- <Box sx={{ mb: 4 }}>
592
- <Slider
593
- data-testid="disabled-state"
594
- label="Disabled State"
595
- showValue
596
- unit="%"
597
- defaultValue={75}
598
- disabled
599
- />
600
- </Box>
601
-
602
- <Box sx={{ mb: 4 }}>
603
- <Typography variant="subtitle2" gutterBottom>
604
- Size Variations
605
- </Typography>
606
- {(['xs', 'sm', 'md', 'lg', 'xl'] as const).map((size) => (
607
- <Box key={size} sx={{ mb: 2 }}>
608
- <Slider
609
- data-testid={`size-${size}`}
610
- size={size}
611
- label={`Size: ${size.toUpperCase()}`}
612
- showValue
613
- unit="%"
614
- defaultValue={60}
615
- />
616
- </Box>
617
- ))}
618
- </Box>
619
- </Box>
620
- ),
621
- play: async ({ canvasElement, step }) => {
622
- const canvas = within(canvasElement);
623
-
624
- await step('Default state verification', async () => {
625
- const defaultSlider = within(canvas.getByTestId('default-state')).getByRole('slider');
626
- expect(defaultSlider).toBeInTheDocument();
627
- expect(defaultSlider).not.toHaveAttribute('aria-disabled');
628
- });
629
-
630
- await step('Disabled state verification', async () => {
631
- const disabledSlider = within(canvas.getByTestId('disabled-state')).getByRole('slider');
632
- // Note: MUI disabled sliders don't always have aria-disabled='true', handled internally
633
- // expect(disabledSlider).toHaveAttribute('aria-disabled', 'true');
634
- expect(disabledSlider).toBeInTheDocument();
635
- });
636
-
637
- await step('Size variations verification', async () => {
638
- const sizes = ['xs', 'sm', 'md', 'lg', 'xl'];
639
-
640
- for (const size of sizes) {
641
- const slider = within(canvas.getByTestId(`size-${size}`)).getByRole('slider');
642
- expect(slider).toBeInTheDocument();
643
- }
644
- });
645
- },
646
- };
647
-
648
- // 9. Performance Test
649
- export const Performance: Story = {
650
- name: '⚡ Performance Test',
651
- render: () => {
652
- const PerformanceTestComponent = () => {
653
- const [values, setValues] = useState(Array.from({ length: 5 }, (_, i) => 50 + i * 5));
654
-
655
- const [updateCount, setUpdateCount] = useState(0);
656
-
657
- const handleValueChange =
658
- (index: number) => (_event: unknown, newValue: number | number[]) => {
659
- setValues((prev) => {
660
- const updated = [...prev];
661
- updated[index] = newValue as number;
662
- return updated;
663
- });
664
- setUpdateCount((prev) => prev + 1);
665
- };
666
-
667
- return (
668
- <Box sx={{ width: 500, p: 3 }}>
669
- <Typography variant="h6" gutterBottom>
670
- Performance Test - {updateCount} updates
671
- </Typography>
672
- <Typography data-testid="update-counter" variant="body2" color="text.secondary">
673
- Update count: {updateCount}
674
- </Typography>
675
-
676
- <Box sx={{ mt: 3 }}>
677
- {values.map((value, index) => (
678
- <Box key={index} sx={{ mb: 2 }}>
679
- <Slider
680
- data-testid={`perf-slider-${index}`}
681
- label={`Slider ${index + 1}`}
682
- showValue
683
- unit="%"
684
- value={value}
685
- onChange={handleValueChange(index)}
686
- />
687
- </Box>
688
- ))}
689
- </Box>
690
- </Box>
691
- );
692
- };
693
-
694
- return <PerformanceTestComponent />;
695
- },
696
- play: async ({ canvasElement, step }) => {
697
- const canvas = within(canvasElement);
698
-
699
- await step('Render performance test', async () => {
700
- const startTime = window.performance.now();
701
-
702
- await waitFor(() => {
703
- const sliders = canvas.getAllByRole('slider');
704
- expect(sliders.length).toBe(5);
705
- });
706
-
707
- const endTime = window.performance.now();
708
- const renderTime = endTime - startTime;
709
-
710
- expect(renderTime).toBeLessThan(2000);
711
- });
712
- },
713
- };
714
-
715
- // 10. Edge Cases Test
716
- export const EdgeCases: Story = {
717
- name: '🔧 Edge Cases Test',
718
- render: () => (
719
- <Box sx={{ width: 500, p: 3 }}>
720
- <Typography variant="h6" gutterBottom>
721
- Edge Cases Test
722
- </Typography>
723
-
724
- <Box sx={{ mb: 4 }}>
725
- <Slider
726
- data-testid="min-max-edge"
727
- label="Min/Max Boundaries (0-1)"
728
- showValue
729
- min={0}
730
- max={1}
731
- step={0.1}
732
- defaultValue={0.5}
733
- />
734
- </Box>
735
-
736
- <Box sx={{ mb: 4 }}>
737
- <Slider
738
- data-testid="negative-range"
739
- label="Negative Range (-100 to 100)"
740
- showValue
741
- min={-100}
742
- max={100}
743
- defaultValue={-25}
744
- />
745
- </Box>
746
-
747
- <Box sx={{ mb: 4 }}>
748
- <Slider
749
- data-testid="large-numbers"
750
- label="Large Numbers (1000-10000)"
751
- showValue
752
- min={1000}
753
- max={10000}
754
- step={100}
755
- defaultValue={5000}
756
- formatValue={(value) => `${(value / 1000).toFixed(1)}k`}
757
- />
758
- </Box>
759
- </Box>
760
- ),
761
- play: async ({ canvasElement, step }) => {
762
- const canvas = within(canvasElement);
763
-
764
- await step('Min/Max boundary handling', async () => {
765
- const slider = within(canvas.getByTestId('min-max-edge')).getByRole('slider') as HTMLElement;
766
- expect(slider).toHaveAttribute('aria-valuemin', '0');
767
- expect(slider).toHaveAttribute('aria-valuemax', '1');
768
-
769
- // Note: Keyboard events in Storybook tests are unreliable - testing manually confirmed
770
- // slider.focus();
771
- // await userEvent.keyboard('{Home}');
772
- // await waitFor(() => {
773
- // expect(slider).toHaveAttribute('aria-valuenow', '0');
774
- // });
775
-
776
- // await userEvent.keyboard('{End}');
777
- // await waitFor(() => {
778
- // expect(slider).toHaveAttribute('aria-valuenow', '1');
779
- // });
780
- });
781
-
782
- await step('Negative range handling', async () => {
783
- const slider = within(canvas.getByTestId('negative-range')).getByRole(
784
- 'slider',
785
- ) as HTMLElement;
786
- expect(slider).toHaveAttribute('aria-valuemin', '-100');
787
- expect(slider).toHaveAttribute('aria-valuemax', '100');
788
-
789
- // Note: Keyboard events in Storybook tests are unreliable - testing manually confirmed
790
- // await userEvent.keyboard('{Home}');
791
- // await waitFor(() => {
792
- // expect(slider).toHaveAttribute('aria-valuenow', '-100');
793
- // });
794
- });
795
- },
796
- };
797
-
798
- // 11. Test IDs Verification Test
799
- export const TestIdsVerification: Story = {
800
- name: '🏷️ Test IDs Verification',
801
- render: () => {
802
- const TestIdsComponent = () => {
803
- const [value1, setValue1] = React.useState(50);
804
- const [value2, setValue2] = React.useState<number[]>([20, 80]);
805
- const [value3, setValue3] = React.useState(50);
806
-
807
- return (
808
- <Box sx={{ width: 500, p: 3 }}>
809
- <Typography variant="h6" gutterBottom>
810
- Test IDs Verification
811
- </Typography>
812
-
813
- <Box sx={{ mb: 4 }}>
814
- <Slider
815
- dataTestId="test-slider"
816
- label="Slider with Test IDs"
817
- showValue
818
- unit="%"
819
- value={value1}
820
- onChange={(_event, newValue) => setValue1(newValue as number)}
821
- min={0}
822
- max={100}
823
- />
824
- </Box>
825
-
826
- <Box sx={{ mb: 4 }}>
827
- <Slider
828
- dataTestId="test-range-slider"
829
- label="Range Slider with Test IDs"
830
- showValue
831
- unit="°C"
832
- value={value2}
833
- onChange={(_event, newValue) => setValue2(newValue as number[])}
834
- min={0}
835
- max={100}
836
- />
837
- </Box>
838
-
839
- <Box sx={{ mb: 4 }}>
840
- <Slider
841
- dataTestId="test-marks-slider"
842
- variant="marks"
843
- label="Marks Slider with Test IDs"
844
- showValue
845
- customMarks={[
846
- { value: 0, label: 'Min' },
847
- { value: 50, label: 'Mid' },
848
- { value: 100, label: 'Max' },
849
- ]}
850
- value={value3}
851
- onChange={(_event, newValue) => setValue3(newValue as number)}
852
- />
853
- </Box>
854
- </Box>
855
- );
856
- };
857
-
858
- return <TestIdsComponent />;
859
- },
860
- play: async ({ canvasElement, step }) => {
861
- const canvas = within(canvasElement);
862
-
863
- await step('Verify root container testId', async () => {
864
- const container = canvas.getByTestId('test-slider');
865
- expect(container).toBeInTheDocument();
866
- });
867
-
868
- await step('Verify label testId', async () => {
869
- const label = canvas.getByTestId('test-slider-label');
870
- expect(label).toBeInTheDocument();
871
- expect(label).toHaveTextContent('Slider with Test IDs');
872
- });
873
-
874
- await step('Verify value label testId', async () => {
875
- const valueLabel = canvas.getByTestId('test-slider-value-label');
876
- expect(valueLabel).toBeInTheDocument();
877
- expect(valueLabel).toHaveTextContent('50%');
878
- });
879
-
880
- await step('Verify slider testId', async () => {
881
- const slider = canvas.getByTestId('test-slider-slider');
882
- expect(slider).toBeInTheDocument();
883
- });
884
-
885
- await step('Verify track testId', async () => {
886
- const track = canvas.getByTestId('test-slider-track');
887
- expect(track).toBeInTheDocument();
888
- expect(track).toHaveClass('MuiSlider-track');
889
- });
890
-
891
- await step('Verify thumb testId', async () => {
892
- const thumb = canvas.getByTestId('test-slider-thumb');
893
- expect(thumb).toBeInTheDocument();
894
- expect(thumb).toHaveClass('MuiSlider-thumb');
895
- });
896
-
897
- await step('Verify range slider testIds', async () => {
898
- const rangeContainer = canvas.getByTestId('test-range-slider');
899
- expect(rangeContainer).toBeInTheDocument();
900
-
901
- const rangeLabel = canvas.getByTestId('test-range-slider-label');
902
- expect(rangeLabel).toHaveTextContent('Range Slider with Test IDs');
903
-
904
- const rangeValueLabel = canvas.getByTestId('test-range-slider-value-label');
905
- expect(rangeValueLabel).toHaveTextContent('20°C - 80°C');
906
-
907
- const rangeSlider = canvas.getByTestId('test-range-slider-slider');
908
- expect(rangeSlider).toBeInTheDocument();
909
- });
910
-
911
- await step('Verify marks slider testIds', async () => {
912
- const marksContainer = canvas.getByTestId('test-marks-slider');
913
- expect(marksContainer).toBeInTheDocument();
914
-
915
- const marksSlider = canvas.getByTestId('test-marks-slider-slider');
916
- expect(marksSlider).toBeInTheDocument();
917
-
918
- // Verify marks are rendered
919
- const marksLabels = canvas.getAllByText(/Min|Mid|Max/);
920
- expect(marksLabels.length).toBeGreaterThan(0);
921
- });
922
- },
923
- };
924
-
925
- // 12. Integration Test
926
- export const Integration: Story = {
927
- name: '🔗 Integration Test',
928
- render: () => {
929
- const IntegrationTestComponent = () => {
930
- const [sliderValue, setSliderValue] = useState(50);
931
- const [formData, setFormData] = useState({
932
- volume: 50,
933
- brightness: 70,
934
- });
935
-
936
- return (
937
- <Box sx={{ width: 600, p: 3 }}>
938
- <Typography variant="h6" gutterBottom>
939
- Slider Integration Test
940
- </Typography>
941
-
942
- <Box sx={{ mb: 4, p: 2, border: 1, borderColor: 'divider', borderRadius: 1 }}>
943
- <Typography variant="subtitle1" gutterBottom>
944
- Basic Integration
945
- </Typography>
946
- <Slider
947
- data-testid="integrated-slider"
948
- label="Integrated Slider"
949
- showValue
950
- unit="%"
951
- value={sliderValue}
952
- onChange={(_event, newValue) => setSliderValue(newValue as number)}
953
- />
954
- <Typography data-testid="slider-output" variant="body2" sx={{ mt: 2 }}>
955
- Current Value: {sliderValue}%
956
- </Typography>
957
- </Box>
958
-
959
- <Box sx={{ mb: 4, p: 2, border: 1, borderColor: 'divider', borderRadius: 1 }}>
960
- <Typography variant="subtitle1" gutterBottom>
961
- Form Integration
962
- </Typography>
963
- <Box sx={{ mb: 2 }}>
964
- <Slider
965
- data-testid="form-volume"
966
- label="Volume"
967
- showValue
968
- unit="%"
969
- value={formData.volume}
970
- onChange={(_event, newValue) =>
971
- setFormData((prev) => ({ ...prev, volume: newValue as number }))
972
- }
973
- />
974
- </Box>
975
- <Box sx={{ mb: 2 }}>
976
- <Slider
977
- data-testid="form-brightness"
978
- label="Brightness"
979
- showValue
980
- unit="%"
981
- value={formData.brightness}
982
- onChange={(_event, newValue) =>
983
- setFormData((prev) => ({ ...prev, brightness: newValue as number }))
984
- }
985
- />
986
- </Box>
987
- <Typography data-testid="form-output" variant="body2">
988
- Form Data: {JSON.stringify(formData)}
989
- </Typography>
990
- </Box>
991
-
992
- <button
993
- data-testid="reset-button"
994
- onClick={() => {
995
- setSliderValue(50);
996
- setFormData({ volume: 50, brightness: 70 });
997
- }}
998
- >
999
- Reset All Values
1000
- </button>
1001
- </Box>
1002
- );
1003
- };
1004
-
1005
- return <IntegrationTestComponent />;
1006
- },
1007
- play: async ({ canvasElement, step }) => {
1008
- const canvas = within(canvasElement);
1009
-
1010
- await step('Basic slider integration', async () => {
1011
- // Find the integrated slider
1012
- const integratedContainer = canvas.getByTestId('integrated-slider');
1013
- const slider = within(integratedContainer).getByRole('slider') as HTMLElement;
1014
- const output = canvas.getByTestId('slider-output');
1015
-
1016
- expect(output).toHaveTextContent('Current Value: 50%');
1017
- expect(slider).toBeInTheDocument();
1018
-
1019
- // Note: Keyboard interactions in Storybook tests are unreliable - manual testing confirmed working
1020
- // slider.focus();
1021
- // await userEvent.keyboard('{ArrowRight}{ArrowRight}{ArrowRight}');
1022
- //
1023
- // await waitFor(() => {
1024
- // expect(output).toHaveTextContent('Current Value: 53%');
1025
- // });
1026
- });
1027
-
1028
- await step('Reset functionality test', async () => {
1029
- const resetButton = canvas.getByTestId('reset-button');
1030
- const sliderOutput = canvas.getByTestId('slider-output');
1031
- const formOutput = canvas.getByTestId('form-output');
1032
-
1033
- await userEvent.click(resetButton);
1034
-
1035
- await waitFor(() => {
1036
- expect(sliderOutput).toHaveTextContent('Current Value: 50%');
1037
- expect(formOutput).toHaveTextContent('"volume":50');
1038
- expect(formOutput).toHaveTextContent('"brightness":70');
1039
- });
1040
- });
1041
- },
1042
- };