@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.
- package/package.json +17 -9
- package/src/button/index.ts +1 -0
- package/src/social-login-button/index.ts +1 -0
- package/src/{social-login-button.tsx → social-login-button/social-login-button.tsx} +5 -5
- package/src/user-avatar/index.ts +1 -0
- package/src/{user-avatar.tsx → user-avatar/user-avatar.tsx} +4 -4
- package/eslint.config.js +0 -89
- package/src/__tests__/data-grid.test.tsx +0 -125
- package/src/__tests__/package-wiring.test.ts +0 -41
- package/src/__tests__/setup.ts +0 -1
- package/src/__tests__/social-login-button.test.tsx +0 -186
- package/src/__tests__/user-avatar.test.tsx +0 -195
- package/src/__tests__/viewport.test.ts +0 -50
- package/src/components/command/__tests__/command.test.tsx +0 -112
- package/src/components/data-display/Alert/Alert.stories.tsx +0 -559
- package/src/components/data-display/Alert/Alert.test.stories.tsx +0 -707
- package/src/components/data-display/AlertDialog/AlertDialog.stories.tsx +0 -362
- package/src/components/data-display/AlertDialog/AlertDialog.test.stories.tsx +0 -763
- package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.stories.tsx +0 -230
- package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.test.stories.tsx +0 -270
- package/src/components/data-display/Avatar/Avatar.stories.tsx +0 -721
- package/src/components/data-display/Avatar/Avatar.test.stories.tsx +0 -822
- package/src/components/data-display/Badge/Badge.stories.tsx +0 -1134
- package/src/components/data-display/Badge/Badge.test.stories.tsx +0 -1194
- package/src/components/data-display/Banner/Banner.stories.tsx +0 -528
- package/src/components/data-display/Banner/Banner.test.stories.tsx +0 -511
- package/src/components/data-display/Carousel/Carousel.stories.tsx +0 -607
- package/src/components/data-display/Carousel/Carousel.test.stories.tsx +0 -701
- package/src/components/data-display/Chart/Chart.stories.tsx +0 -568
- package/src/components/data-display/Chart/Chart.test.stories.tsx +0 -174
- package/src/components/data-display/Chart/SpecChart.stories.tsx +0 -150
- package/src/components/data-display/Chart/SpecChart.test.stories.tsx +0 -56
- package/src/components/data-display/Chart/__tests__/SpecChart.test.tsx +0 -60
- package/src/components/data-display/Chart/__tests__/chart-format.test.ts +0 -43
- package/src/components/data-display/Chart/__tests__/chart-spec.test.ts +0 -119
- package/src/components/data-display/Chip/Chip.stories.tsx +0 -252
- package/src/components/data-display/Chip/Chip.test.stories.tsx +0 -266
- package/src/components/data-display/DataGrid/DataGrid.stories.tsx +0 -515
- package/src/components/data-display/DataGrid/DataGrid.test.stories.tsx +0 -653
- package/src/components/data-display/DataViews/__tests__/DataViewsGrid.test.tsx +0 -271
- package/src/components/data-display/DataViews/__tests__/DataViewsTableBase.test.tsx +0 -134
- package/src/components/data-display/DataViews/__tests__/SaveViewModal.test.tsx +0 -83
- package/src/components/data-display/DataViews/__tests__/data-views-filter.test.ts +0 -115
- package/src/components/data-display/DataViews/__tests__/data-views-preview.test.ts +0 -53
- package/src/components/data-display/DataViews/__tests__/range-pill.test.tsx +0 -114
- package/src/components/data-display/DataViews/base-card.stories.tsx +0 -136
- package/src/components/data-display/DescriptionItem/DescriptionItem.stories.tsx +0 -254
- package/src/components/data-display/EmptyState/EmptyState.stories.tsx +0 -282
- package/src/components/data-display/EmptyState/EmptyState.test.stories.tsx +0 -441
- package/src/components/data-display/ErrorState/ErrorState.stories.tsx +0 -110
- package/src/components/data-display/ErrorState/ErrorState.test.stories.tsx +0 -133
- package/src/components/data-display/HoverCard/HoverCard.stories.tsx +0 -650
- package/src/components/data-display/HoverCard/HoverCard.test.stories.tsx +0 -929
- package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.stories.tsx +0 -411
- package/src/components/data-display/LazyImage/LazyImage.stories.tsx +0 -387
- package/src/components/data-display/Lightbox/Lightbox.stories.tsx +0 -315
- package/src/components/data-display/Lightbox/Lightbox.test.stories.tsx +0 -598
- package/src/components/data-display/LoadingState/LoadingState.stories.tsx +0 -124
- package/src/components/data-display/LoadingState/LoadingState.test.stories.tsx +0 -99
- package/src/components/data-display/MapPreview/MapPreview.stories.tsx +0 -458
- package/src/components/data-display/MapPreview/MapPreview.test.stories.tsx +0 -394
- package/src/components/data-display/Popover/Popover.stories.tsx +0 -295
- package/src/components/data-display/Popover/Popover.test.stories.tsx +0 -1162
- package/src/components/data-display/Progress/Progress.stories.tsx +0 -481
- package/src/components/data-display/Progress/Progress.test.stories.tsx +0 -2070
- package/src/components/data-display/SectionOnboarding/SectionOnboarding.stories.tsx +0 -160
- package/src/components/data-display/SectionOnboarding/SectionOnboarding.test.stories.tsx +0 -190
- package/src/components/data-display/Sheet/Sheet.stories.tsx +0 -883
- package/src/components/data-display/Sheet/Sheet.test.stories.tsx +0 -1105
- package/src/components/data-display/StatCard/StatCard.stories.tsx +0 -167
- package/src/components/data-display/StatCard/StatCard.test.stories.tsx +0 -240
- package/src/components/data-display/Stepper/Stepper.stories.tsx +0 -540
- package/src/components/data-display/Stepper/Stepper.test.stories.tsx +0 -600
- package/src/components/data-display/Table/Table.stories.tsx +0 -803
- package/src/components/data-display/Table/Table.test.stories.tsx +0 -369
- package/src/components/data-display/Timeline/Timeline.stories.tsx +0 -442
- package/src/components/data-display/Timeline/Timeline.test.stories.tsx +0 -930
- package/src/components/data-display/TimingDiagram/TimingDiagram.stories.tsx +0 -475
- package/src/components/data-display/TimingDiagram/TimingDiagram.test.stories.tsx +0 -734
- package/src/components/data-display/Tooltip/Tooltip.stories.tsx +0 -468
- package/src/components/data-display/Tooltip/Tooltip.test.stories.tsx +0 -1154
- package/src/components/feedback/ConfirmAction/ConfirmAction.stories.tsx +0 -146
- package/src/components/feedback/ConfirmAction/ConfirmAction.test.stories.tsx +0 -114
- package/src/components/feedback/ConfirmAction/__tests__/confirm-action.test.tsx +0 -288
- package/src/components/feedback/Dialog/Dialog.stories.tsx +0 -833
- package/src/components/feedback/Dialog/Dialog.test.stories.tsx +0 -964
- package/src/components/feedback/Dialog/__tests__/dialog-content-spacing.test.tsx +0 -66
- package/src/components/feedback/Modal/Modal.stories.tsx +0 -765
- package/src/components/feedback/Modal/Modal.test.stories.tsx +0 -251
- package/src/components/feedback/Sonner/Sonner.stories.tsx +0 -698
- package/src/components/feedback/Sonner/Sonner.test.stories.tsx +0 -896
- package/src/components/feedback/StackedModal/StackedModal.stories.tsx +0 -1783
- package/src/components/feedback/StackedModal/StackedModal.test.stories.tsx +0 -973
- package/src/components/feedback/StackedModal/__tests__/stacked-modal-viewport.test.tsx +0 -104
- package/src/components/feedback/Toast/Toast.stories.tsx +0 -548
- package/src/components/feedback/Toast/Toast.test.stories.tsx +0 -834
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.stories.tsx +0 -691
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.test.stories.tsx +0 -634
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.stories.tsx +0 -665
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.test.stories.tsx +0 -727
- package/src/components/form/Autocomplete/Autocomplete.stories.tsx +0 -715
- package/src/components/form/Autocomplete/Autocomplete.test.stories.tsx +0 -825
- package/src/components/form/Button/Button.stories.tsx +0 -365
- package/src/components/form/Button/Button.test.stories.tsx +0 -607
- package/src/components/form/Calendar/Calendar.stories.tsx +0 -349
- package/src/components/form/Calendar/Calendar.test.stories.tsx +0 -464
- package/src/components/form/CepField/CepField.stories.tsx +0 -138
- package/src/components/form/CepField/CepField.test.stories.tsx +0 -281
- package/src/components/form/Checkbox/Checkbox.stories.tsx +0 -265
- package/src/components/form/Checkbox/Checkbox.test.stories.tsx +0 -181
- package/src/components/form/CodeEditor/CodeEditor.stories.tsx +0 -871
- package/src/components/form/CodeEditor/CodeEditor.test.stories.tsx +0 -574
- package/src/components/form/Command/Command.stories.tsx +0 -580
- package/src/components/form/Command/Command.test.stories.tsx +0 -215
- package/src/components/form/CreatableSelect/CreatableSelect.stories.tsx +0 -112
- package/src/components/form/CreatableSelect/CreatableSelect.test.stories.tsx +0 -134
- package/src/components/form/Form/Form.stories.tsx +0 -687
- package/src/components/form/Form/Form.test.stories.tsx +0 -601
- package/src/components/form/Input/Input.stories.tsx +0 -260
- package/src/components/form/Input/Input.test.stories.tsx +0 -1191
- package/src/components/form/InputOTP/InputOTP.stories.tsx +0 -774
- package/src/components/form/InputOTP/InputOTP.test.stories.tsx +0 -588
- package/src/components/form/Label/Label.stories.tsx +0 -473
- package/src/components/form/Label/Label.test.stories.tsx +0 -915
- package/src/components/form/Menubar/Menubar.stories.tsx +0 -472
- package/src/components/form/Menubar/Menubar.test.stories.tsx +0 -584
- package/src/components/form/PasswordStrength/PasswordStrength.stories.tsx +0 -562
- package/src/components/form/PasswordStrength/PasswordStrength.test.stories.tsx +0 -327
- package/src/components/form/PhoneInput/PhoneInput.stories.tsx +0 -495
- package/src/components/form/PhoneInput/PhoneInput.test.stories.tsx +0 -666
- package/src/components/form/RadioGroup/RadioGroup.stories.tsx +0 -518
- package/src/components/form/RadioGroup/RadioGroup.test.stories.tsx +0 -685
- package/src/components/form/RichTextEditor/RichTextEditor.stories.tsx +0 -261
- package/src/components/form/RichTextEditor/RichTextEditor.test.stories.tsx +0 -491
- package/src/components/form/SearchPalette/SearchPalette.stories.tsx +0 -135
- package/src/components/form/Select/Select.stories.tsx +0 -364
- package/src/components/form/Select/Select.test.stories.tsx +0 -985
- package/src/components/form/Slider/Slider.stories.tsx +0 -418
- package/src/components/form/Slider/Slider.test.stories.tsx +0 -1042
- package/src/components/form/Switch/Switch.stories.tsx +0 -697
- package/src/components/form/Switch/Switch.test.stories.tsx +0 -597
- package/src/components/form/Textarea/Textarea.stories.tsx +0 -473
- package/src/components/form/Textarea/Textarea.test.stories.tsx +0 -702
- package/src/components/form/Toggle/Toggle.stories.tsx +0 -638
- package/src/components/form/Toggle/Toggle.test.stories.tsx +0 -1159
- package/src/components/form/ToggleGroup/ToggleGroup.stories.tsx +0 -617
- package/src/components/form/ToggleGroup/ToggleGroup.test.stories.tsx +0 -915
- package/src/components/form/UploadButton/UploadButton.stories.tsx +0 -367
- package/src/components/form/UploadButton/UploadButton.test.stories.tsx +0 -573
- package/src/components/form/total-form/total-form.test.tsx +0 -214
- package/src/components/layout/Accordion/Accordion.stories.tsx +0 -694
- package/src/components/layout/Accordion/Accordion.test.stories.tsx +0 -1344
- package/src/components/layout/Card/Card.stories.tsx +0 -591
- package/src/components/layout/Card/Card.test.stories.tsx +0 -1134
- package/src/components/layout/CardGrid/__tests__/CardGrid.test.tsx +0 -92
- package/src/components/layout/Collapsible/Collapsible.stories.tsx +0 -180
- package/src/components/layout/Collapsible/Collapsible.test.stories.tsx +0 -308
- package/src/components/layout/Container/Container.stories.tsx +0 -557
- package/src/components/layout/Container/Container.test.stories.tsx +0 -745
- package/src/components/layout/ContentToolbar/ContentToolbar.stories.tsx +0 -129
- package/src/components/layout/ContentToolbar/ContentToolbar.test.stories.tsx +0 -251
- package/src/components/layout/ContentToolbar/__tests__/ColumnsMenu.test.tsx +0 -39
- package/src/components/layout/ContentToolbar/__tests__/MultiSelectDropdown.test.tsx +0 -131
- package/src/components/layout/ContentToolbar/__tests__/SavedViewsMenu.test.tsx +0 -99
- package/src/components/layout/Dashboard/Dashboard.stories.tsx +0 -104
- package/src/components/layout/Dashboard/Dashboard.test.stories.tsx +0 -190
- package/src/components/layout/Drawer/Drawer.stories.tsx +0 -658
- package/src/components/layout/Drawer/Drawer.test.stories.tsx +0 -1343
- package/src/components/layout/Resizable/Resizable.stories.tsx +0 -1039
- package/src/components/layout/Resizable/Resizable.test.stories.tsx +0 -754
- package/src/components/layout/ScrollArea/ScrollArea.stories.tsx +0 -651
- package/src/components/layout/ScrollArea/ScrollArea.test.stories.tsx +0 -619
- package/src/components/layout/Separator/Separator.stories.tsx +0 -563
- package/src/components/layout/Separator/Separator.test.stories.tsx +0 -518
- package/src/components/layout/SettingsLayout/SettingsLayout.stories.tsx +0 -192
- package/src/components/layout/SettingsLayout/SettingsLayout.test.stories.tsx +0 -175
- package/src/components/layout/Sidebar/Sidebar.stories.tsx +0 -609
- package/src/components/layout/Sidebar/Sidebar.test.stories.tsx +0 -1324
- package/src/components/layout/Skeleton/Skeleton.stories.tsx +0 -689
- package/src/components/layout/Skeleton/Skeleton.test.stories.tsx +0 -521
- package/src/components/layout/Spacer/Spacer.stories.tsx +0 -502
- package/src/components/layout/Spacer/Spacer.test.stories.tsx +0 -474
- package/src/components/layout/TableFilter/TableFilter.stories.tsx +0 -82
- package/src/components/layout/TableFilter/TableFilter.test.stories.tsx +0 -87
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.stories.tsx +0 -638
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.test.stories.tsx +0 -1008
- package/src/components/navigation/CommandPalette/CommandPalette.stories.tsx +0 -386
- package/src/components/navigation/CommandPalette/CommandPalette.test.stories.tsx +0 -435
- package/src/components/navigation/ContextMenu/ContextMenu.stories.tsx +0 -614
- package/src/components/navigation/ContextMenu/ContextMenu.test.stories.tsx +0 -845
- package/src/components/navigation/DropdownMenu/DropdownMenu.stories.tsx +0 -578
- package/src/components/navigation/DropdownMenu/DropdownMenu.test.stories.tsx +0 -660
- package/src/components/navigation/NavigationMenu/stories/NavigationMenu.stories.tsx +0 -516
- package/src/components/navigation/NavigationMenu/stories/NavigationMenu.test.stories.tsx +0 -935
- package/src/components/navigation/NavigationMenu/stories/NavigationMenuHorizontal.stories.tsx +0 -501
- package/src/components/navigation/NavigationMenu/stories/NavigationMenuVertical.stories.tsx +0 -453
- package/src/components/navigation/Pagination/Pagination.stories.tsx +0 -602
- package/src/components/navigation/Pagination/Pagination.test.stories.tsx +0 -520
- package/src/components/navigation/Tabs/Tabs.stories.tsx +0 -1004
- package/src/components/navigation/Tabs/Tabs.test.stories.tsx +0 -1225
- package/src/components/typography/Blockquote/Blockquote.stories.tsx +0 -359
- package/src/components/typography/Blockquote/Blockquote.test.stories.tsx +0 -432
- package/src/components/typography/Code/Code.stories.tsx +0 -686
- package/src/components/typography/Code/Code.test.stories.tsx +0 -703
- package/src/components/typography/Heading/Heading.stories.tsx +0 -451
- package/src/components/typography/Heading/Heading.test.stories.tsx +0 -830
- package/src/components/typography/Paragraph/Paragraph.stories.tsx +0 -280
- package/src/components/typography/Paragraph/Paragraph.test.stories.tsx +0 -231
- package/src/components/typography/Text/Text.stories.tsx +0 -359
- package/src/components/typography/Text/Text.test.stories.tsx +0 -759
- package/src/components/utility/AnimatedIcon/AnimatedIcon.stories.tsx +0 -945
- package/src/components/utility/AnimatedIcon/AnimatedIcon.test.stories.tsx +0 -603
- package/src/components/utility/AspectRatio/AspectRatio.stories.tsx +0 -414
- package/src/components/utility/AspectRatio/AspectRatio.test.stories.tsx +0 -859
- package/src/components/utility/InfiniteScroll/InfiniteScroll.stories.tsx +0 -620
- package/src/components/utility/InfiniteScroll/InfiniteScroll.test.stories.tsx +0 -361
- package/src/components/utility/InstallPrompt/InstallPrompt.stories.tsx +0 -118
- package/src/components/utility/InstallPrompt/InstallPrompt.test.stories.tsx +0 -83
- package/src/components/utility/InstallPrompt/__tests__/InstallPrompt.ios.test.tsx +0 -65
- package/src/components/utility/InstallPrompt/__tests__/usePwaInstall.test.tsx +0 -271
- package/src/components/utility/Portal/Portal.stories.tsx +0 -340
- package/src/components/utility/Portal/Portal.test.stories.tsx +0 -2086
- package/src/components/utility/Transition/Transition.stories.tsx +0 -493
- package/src/components/utility/Transition/Transition.test.stories.tsx +0 -854
- package/src/components/utility/VirtualList/VirtualList.stories.tsx +0 -1073
- package/src/components/utility/VirtualList/VirtualList.test.stories.tsx +0 -1085
- package/src/components/utility/WorkflowStep/WorkflowStep.stories.tsx +0 -431
- package/src/components/utility/WorkflowStep/WorkflowStep.test.stories.tsx +0 -364
- /package/src/{button.tsx → button/button.tsx} +0 -0
|
@@ -1,915 +0,0 @@
|
|
|
1
|
-
import { Box, Typography } from '@mui/material';
|
|
2
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
|
-
import {
|
|
4
|
-
AlignCenter,
|
|
5
|
-
AlignLeft,
|
|
6
|
-
AlignRight,
|
|
7
|
-
Bold,
|
|
8
|
-
Bookmark,
|
|
9
|
-
Heart,
|
|
10
|
-
Italic,
|
|
11
|
-
Monitor,
|
|
12
|
-
Moon,
|
|
13
|
-
Star,
|
|
14
|
-
Sun,
|
|
15
|
-
Underline,
|
|
16
|
-
} from 'lucide-react';
|
|
17
|
-
import React from 'react';
|
|
18
|
-
import { expect, fn,userEvent, waitFor, within } from 'storybook/test';
|
|
19
|
-
|
|
20
|
-
import { ToggleGroup } from './ToggleGroup';
|
|
21
|
-
|
|
22
|
-
const meta: Meta<typeof ToggleGroup> = {
|
|
23
|
-
title: 'Form/ToggleGroup/Tests',
|
|
24
|
-
component: ToggleGroup,
|
|
25
|
-
parameters: {
|
|
26
|
-
layout: 'centered',
|
|
27
|
-
chromatic: { disableSnapshot: false },
|
|
28
|
-
},
|
|
29
|
-
tags: ['autodocs', 'test', 'component:ToggleGroup'],
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export default meta;
|
|
33
|
-
type Story = StoryObj<typeof meta>;
|
|
34
|
-
|
|
35
|
-
// Test options for different scenarios
|
|
36
|
-
const formatOptions = [
|
|
37
|
-
{ value: 'bold', label: 'Bold', icon: <Bold size={16} /> },
|
|
38
|
-
{ value: 'italic', label: 'Italic', icon: <Italic size={16} /> },
|
|
39
|
-
{ value: 'underline', label: 'Underline', icon: <Underline size={16} /> },
|
|
40
|
-
];
|
|
41
|
-
|
|
42
|
-
const alignOptions = [
|
|
43
|
-
{ value: 'left', label: 'Left', icon: <AlignLeft size={16} /> },
|
|
44
|
-
{ value: 'center', label: 'Center', icon: <AlignCenter size={16} /> },
|
|
45
|
-
{ value: 'right', label: 'Right', icon: <AlignRight size={16} /> },
|
|
46
|
-
];
|
|
47
|
-
|
|
48
|
-
const themeOptions = [
|
|
49
|
-
{ value: 'light', label: 'Light', icon: <Sun size={16} /> },
|
|
50
|
-
{ value: 'dark', label: 'Dark', icon: <Moon size={16} /> },
|
|
51
|
-
{ value: 'system', label: 'System', icon: <Monitor size={16} /> },
|
|
52
|
-
];
|
|
53
|
-
|
|
54
|
-
const actionOptions = [
|
|
55
|
-
{ value: 'like', label: 'Like', icon: <Heart size={16} /> },
|
|
56
|
-
{ value: 'star', label: 'Star', icon: <Star size={16} /> },
|
|
57
|
-
{ value: 'bookmark', label: 'Save', icon: <Bookmark size={16} /> },
|
|
58
|
-
];
|
|
59
|
-
|
|
60
|
-
const optionsWithDisabled = [
|
|
61
|
-
{ value: 'option1', label: 'Available', icon: <Star size={16} /> },
|
|
62
|
-
{ value: 'option2', label: 'Disabled', icon: <Heart size={16} />, disabled: true },
|
|
63
|
-
{ value: 'option3', label: 'Available', icon: <Bookmark size={16} /> },
|
|
64
|
-
];
|
|
65
|
-
|
|
66
|
-
// Component for controlled testing
|
|
67
|
-
const ControlledBasicInteraction = () => {
|
|
68
|
-
const [value, setValue] = React.useState<string>('');
|
|
69
|
-
|
|
70
|
-
return (
|
|
71
|
-
<ToggleGroup
|
|
72
|
-
options={alignOptions}
|
|
73
|
-
variant="single"
|
|
74
|
-
value={value}
|
|
75
|
-
onChange={(_, newValue) => setValue(newValue || '')}
|
|
76
|
-
/>
|
|
77
|
-
);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
// 1. Basic Interaction Tests
|
|
81
|
-
export const BasicInteraction: Story = {
|
|
82
|
-
render: () => <ControlledBasicInteraction />,
|
|
83
|
-
play: async ({ canvasElement }) => {
|
|
84
|
-
const canvas = within(canvasElement);
|
|
85
|
-
|
|
86
|
-
// Test initial state
|
|
87
|
-
const toggleButtons = canvas.getAllByRole('button');
|
|
88
|
-
expect(toggleButtons).toHaveLength(3);
|
|
89
|
-
|
|
90
|
-
// Test clicking a button
|
|
91
|
-
await userEvent.click(toggleButtons[0]);
|
|
92
|
-
|
|
93
|
-
// Verify button state changes
|
|
94
|
-
await waitFor(() => {
|
|
95
|
-
expect(toggleButtons[0]).toHaveAttribute('aria-pressed', 'true');
|
|
96
|
-
});
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
// 2. Form Interaction Tests
|
|
101
|
-
export const FormInteraction: Story = {
|
|
102
|
-
args: {
|
|
103
|
-
options: formatOptions,
|
|
104
|
-
variant: 'multiple',
|
|
105
|
-
onChange: fn(),
|
|
106
|
-
value: [],
|
|
107
|
-
},
|
|
108
|
-
play: async ({ canvasElement, args }) => {
|
|
109
|
-
const canvas = within(canvasElement);
|
|
110
|
-
|
|
111
|
-
const toggleButtons = canvas.getAllByRole('button');
|
|
112
|
-
|
|
113
|
-
// Test multiple selection
|
|
114
|
-
await userEvent.click(toggleButtons[0]); // Bold
|
|
115
|
-
await userEvent.click(toggleButtons[2]); // Underline
|
|
116
|
-
|
|
117
|
-
// Verify both calls were made
|
|
118
|
-
await waitFor(() => {
|
|
119
|
-
expect(args.onChange).toHaveBeenCalledTimes(2);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
// Test deselection
|
|
123
|
-
await userEvent.click(toggleButtons[0]); // Unselect Bold
|
|
124
|
-
|
|
125
|
-
await waitFor(() => {
|
|
126
|
-
expect(args.onChange).toHaveBeenCalledTimes(3);
|
|
127
|
-
});
|
|
128
|
-
},
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
// 3. Keyboard Navigation Tests
|
|
132
|
-
export const KeyboardNavigation: Story = {
|
|
133
|
-
args: {
|
|
134
|
-
options: alignOptions,
|
|
135
|
-
variant: 'single',
|
|
136
|
-
onChange: fn(),
|
|
137
|
-
},
|
|
138
|
-
play: async ({ canvasElement, args }) => {
|
|
139
|
-
const canvas = within(canvasElement);
|
|
140
|
-
|
|
141
|
-
const firstButton = canvas.getAllByRole('button')[0];
|
|
142
|
-
|
|
143
|
-
// Focus the first button
|
|
144
|
-
await userEvent.click(firstButton);
|
|
145
|
-
await waitFor(() => {
|
|
146
|
-
expect(firstButton).toHaveFocus();
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// Test Tab navigation between buttons (MUI default behavior)
|
|
150
|
-
await userEvent.tab();
|
|
151
|
-
const secondButton = canvas.getAllByRole('button')[1];
|
|
152
|
-
await waitFor(() => {
|
|
153
|
-
expect(secondButton).toHaveFocus();
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
// Test Space key activation
|
|
157
|
-
await userEvent.keyboard(' ');
|
|
158
|
-
await waitFor(() => {
|
|
159
|
-
expect(args.onChange).toHaveBeenCalled();
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// Test Enter key activation
|
|
163
|
-
await userEvent.keyboard('{Enter}');
|
|
164
|
-
await waitFor(() => {
|
|
165
|
-
expect(args.onChange).toHaveBeenCalledTimes(2);
|
|
166
|
-
});
|
|
167
|
-
},
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
// 4. Screen Reader Tests
|
|
171
|
-
export const ScreenReader: Story = {
|
|
172
|
-
args: {
|
|
173
|
-
options: themeOptions,
|
|
174
|
-
variant: 'single',
|
|
175
|
-
'aria-label': 'Theme selector',
|
|
176
|
-
},
|
|
177
|
-
play: async ({ canvasElement }) => {
|
|
178
|
-
const canvas = within(canvasElement);
|
|
179
|
-
|
|
180
|
-
// Test ARIA attributes
|
|
181
|
-
const toggleGroup = canvas.getByRole('group');
|
|
182
|
-
expect(toggleGroup).toBeInTheDocument();
|
|
183
|
-
|
|
184
|
-
// Test button roles and labels
|
|
185
|
-
const buttons = canvas.getAllByRole('button');
|
|
186
|
-
|
|
187
|
-
buttons.forEach((button, index) => {
|
|
188
|
-
// MUI ToggleButton doesn't explicitly set role="button" as it's implicit
|
|
189
|
-
expect(button.tagName.toLowerCase()).toBe('button');
|
|
190
|
-
expect(button).toHaveAttribute('aria-pressed');
|
|
191
|
-
|
|
192
|
-
// Verify accessible names
|
|
193
|
-
const option = themeOptions[index];
|
|
194
|
-
expect(button).toHaveAccessibleName(expect.stringContaining(option.label));
|
|
195
|
-
});
|
|
196
|
-
},
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
// 5. Focus Management Tests
|
|
200
|
-
export const FocusManagement: Story = {
|
|
201
|
-
args: {
|
|
202
|
-
options: actionOptions,
|
|
203
|
-
variant: 'single',
|
|
204
|
-
onChange: fn(),
|
|
205
|
-
},
|
|
206
|
-
play: async ({ canvasElement }) => {
|
|
207
|
-
const canvas = within(canvasElement);
|
|
208
|
-
|
|
209
|
-
// Named rather than indexed: a positional lookup silently follows whatever
|
|
210
|
-
// order the options happen to render in, so it keeps passing after a
|
|
211
|
-
// reorder while no longer testing what it says it does.
|
|
212
|
-
const likeButton = canvas.getByRole('button', { name: /like/i });
|
|
213
|
-
const starButton = canvas.getByRole('button', { name: /star/i });
|
|
214
|
-
|
|
215
|
-
// Test initial focus
|
|
216
|
-
await userEvent.click(likeButton);
|
|
217
|
-
await waitFor(() => {
|
|
218
|
-
expect(likeButton).toHaveFocus();
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
// Test focus moves correctly with tab navigation
|
|
222
|
-
await userEvent.tab();
|
|
223
|
-
await waitFor(() => {
|
|
224
|
-
expect(starButton).toHaveFocus();
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
// Test focus doesn't get lost after selection
|
|
228
|
-
await userEvent.click(starButton);
|
|
229
|
-
await waitFor(() => {
|
|
230
|
-
expect(starButton).toHaveFocus();
|
|
231
|
-
});
|
|
232
|
-
},
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
// 6. Responsive Design Tests
|
|
236
|
-
export const ResponsiveDesign: Story = {
|
|
237
|
-
args: {
|
|
238
|
-
options: formatOptions,
|
|
239
|
-
size: 'md',
|
|
240
|
-
},
|
|
241
|
-
parameters: {
|
|
242
|
-
viewport: { defaultViewport: 'mobile1' },
|
|
243
|
-
},
|
|
244
|
-
play: async ({ canvasElement }) => {
|
|
245
|
-
const canvas = within(canvasElement);
|
|
246
|
-
|
|
247
|
-
// Test component renders on small screens
|
|
248
|
-
const toggleGroup = canvas.getByRole('group');
|
|
249
|
-
expect(toggleGroup).toBeInTheDocument();
|
|
250
|
-
|
|
251
|
-
// Test buttons are still accessible
|
|
252
|
-
const buttons = canvas.getAllByRole('button');
|
|
253
|
-
expect(buttons).toHaveLength(3);
|
|
254
|
-
|
|
255
|
-
// Test buttons maintain minimum touch target size (44px)
|
|
256
|
-
buttons.forEach((button) => {
|
|
257
|
-
const styles = window.getComputedStyle(button);
|
|
258
|
-
const height = parseInt(styles.height);
|
|
259
|
-
expect(height).toBeGreaterThanOrEqual(40); // Allow some margin for borders/padding
|
|
260
|
-
});
|
|
261
|
-
},
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
// 7. Theme Variations Tests
|
|
265
|
-
export const ThemeVariations: Story = {
|
|
266
|
-
render: () => (
|
|
267
|
-
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
|
|
268
|
-
{(['primary', 'secondary', 'success', 'warning', 'danger'] as const).map((color) => (
|
|
269
|
-
<Box key={color}>
|
|
270
|
-
<Typography variant="h6" gutterBottom sx={{ textTransform: 'capitalize' }}>
|
|
271
|
-
{color}
|
|
272
|
-
</Typography>
|
|
273
|
-
<ToggleGroup color={color} options={alignOptions} data-testid={`toggle-group-${color}`} />
|
|
274
|
-
</Box>
|
|
275
|
-
))}
|
|
276
|
-
</Box>
|
|
277
|
-
),
|
|
278
|
-
play: async ({ canvasElement }) => {
|
|
279
|
-
const canvas = within(canvasElement);
|
|
280
|
-
|
|
281
|
-
// Test each color variant renders
|
|
282
|
-
const colors = ['primary', 'secondary', 'success', 'warning', 'danger'];
|
|
283
|
-
|
|
284
|
-
for (const color of colors) {
|
|
285
|
-
const toggleGroup = canvas.getByTestId(`toggle-group-${color}`);
|
|
286
|
-
expect(toggleGroup).toBeInTheDocument();
|
|
287
|
-
|
|
288
|
-
// Test buttons within each color variant
|
|
289
|
-
const buttons = within(toggleGroup).getAllByRole('button');
|
|
290
|
-
expect(buttons).toHaveLength(3);
|
|
291
|
-
}
|
|
292
|
-
},
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
// 8. Visual States Tests
|
|
296
|
-
export const VisualStates: Story = {
|
|
297
|
-
render: () => (
|
|
298
|
-
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
|
299
|
-
<Box>
|
|
300
|
-
<Typography variant="h6" gutterBottom>
|
|
301
|
-
Normal State
|
|
302
|
-
</Typography>
|
|
303
|
-
<ToggleGroup options={alignOptions} data-testid="normal" />
|
|
304
|
-
</Box>
|
|
305
|
-
|
|
306
|
-
<Box>
|
|
307
|
-
<Typography variant="h6" gutterBottom>
|
|
308
|
-
With Disabled Options
|
|
309
|
-
</Typography>
|
|
310
|
-
<ToggleGroup options={optionsWithDisabled} data-testid="disabled" />
|
|
311
|
-
</Box>
|
|
312
|
-
|
|
313
|
-
<Box>
|
|
314
|
-
<Typography variant="h6" gutterBottom>
|
|
315
|
-
Glass Effect
|
|
316
|
-
</Typography>
|
|
317
|
-
<ToggleGroup options={themeOptions} glass data-testid="glass" />
|
|
318
|
-
</Box>
|
|
319
|
-
|
|
320
|
-
<Box>
|
|
321
|
-
<Typography variant="h6" gutterBottom>
|
|
322
|
-
Gradient Effect
|
|
323
|
-
</Typography>
|
|
324
|
-
<ToggleGroup options={actionOptions} gradient color="secondary" data-testid="gradient" />
|
|
325
|
-
</Box>
|
|
326
|
-
|
|
327
|
-
<Box>
|
|
328
|
-
<Typography variant="h6" gutterBottom>
|
|
329
|
-
Size Variations
|
|
330
|
-
</Typography>
|
|
331
|
-
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
332
|
-
{(['xs', 'sm', 'md', 'lg', 'xl'] as const).map((size) => (
|
|
333
|
-
<ToggleGroup
|
|
334
|
-
key={size}
|
|
335
|
-
options={formatOptions}
|
|
336
|
-
size={size}
|
|
337
|
-
data-testid={`size-${size}`}
|
|
338
|
-
/>
|
|
339
|
-
))}
|
|
340
|
-
</Box>
|
|
341
|
-
</Box>
|
|
342
|
-
</Box>
|
|
343
|
-
),
|
|
344
|
-
play: async ({ canvasElement }) => {
|
|
345
|
-
const canvas = within(canvasElement);
|
|
346
|
-
|
|
347
|
-
// Test normal state
|
|
348
|
-
const normalGroup = canvas.getByTestId('normal');
|
|
349
|
-
expect(normalGroup).toBeInTheDocument();
|
|
350
|
-
|
|
351
|
-
// Test disabled options
|
|
352
|
-
const disabledGroup = canvas.getByTestId('disabled');
|
|
353
|
-
const disabledButtons = within(disabledGroup).getAllByRole('button');
|
|
354
|
-
expect(disabledButtons[1]).toBeDisabled();
|
|
355
|
-
expect(disabledButtons[0]).not.toBeDisabled();
|
|
356
|
-
expect(disabledButtons[2]).not.toBeDisabled();
|
|
357
|
-
|
|
358
|
-
// Test glass effect - verify backdrop filter and styling
|
|
359
|
-
const glassGroup = canvas.getByTestId('glass');
|
|
360
|
-
expect(glassGroup).toBeInTheDocument();
|
|
361
|
-
|
|
362
|
-
// Verify glass effect styling is applied
|
|
363
|
-
const styles = window.getComputedStyle(glassGroup);
|
|
364
|
-
expect(styles.backdropFilter).toContain('blur');
|
|
365
|
-
expect(styles.backgroundColor).not.toBe('transparent');
|
|
366
|
-
expect(parseInt(styles.padding)).toBeGreaterThan(0);
|
|
367
|
-
|
|
368
|
-
// Test gradient effect
|
|
369
|
-
const gradientGroup = canvas.getByTestId('gradient');
|
|
370
|
-
expect(gradientGroup).toBeInTheDocument();
|
|
371
|
-
|
|
372
|
-
// Test size variations
|
|
373
|
-
const sizes = ['xs', 'sm', 'md', 'lg', 'xl'];
|
|
374
|
-
for (const size of sizes) {
|
|
375
|
-
const sizeGroup = canvas.getByTestId(`size-${size}`);
|
|
376
|
-
expect(sizeGroup).toBeInTheDocument();
|
|
377
|
-
|
|
378
|
-
const buttons = within(sizeGroup).getAllByRole('button');
|
|
379
|
-
expect(buttons).toHaveLength(3);
|
|
380
|
-
}
|
|
381
|
-
},
|
|
382
|
-
};
|
|
383
|
-
|
|
384
|
-
// 9. Performance Tests
|
|
385
|
-
export const Performance: Story = {
|
|
386
|
-
args: {
|
|
387
|
-
options: Array.from({ length: 20 }, (_, i) => ({
|
|
388
|
-
value: `option-${i}`,
|
|
389
|
-
label: `Option ${i + 1}`,
|
|
390
|
-
icon: <Star size={16} />,
|
|
391
|
-
})),
|
|
392
|
-
variant: 'multiple',
|
|
393
|
-
},
|
|
394
|
-
play: async ({ canvasElement }) => {
|
|
395
|
-
const canvas = within(canvasElement);
|
|
396
|
-
|
|
397
|
-
// All twenty options render — the assertion the wall-clock budgets that used
|
|
398
|
-
// to sit here were standing in for. A millisecond threshold measures the
|
|
399
|
-
// machine running the story, not the component, and the timings were
|
|
400
|
-
// already padded to 100ms and 600ms to survive CI.
|
|
401
|
-
const buttons = canvas.getAllByRole('button');
|
|
402
|
-
expect(buttons).toHaveLength(20);
|
|
403
|
-
|
|
404
|
-
// Clicking a spread of them, by name, still exercises the multi-select path.
|
|
405
|
-
for (const label of ['Option 1', 'Option 6', 'Option 11']) {
|
|
406
|
-
await userEvent.click(canvas.getByRole('button', { name: new RegExp(label + '$') }));
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
await waitFor(() => {
|
|
410
|
-
expect(canvas.getByRole('button', { name: /Option 11$/ })).toHaveAttribute(
|
|
411
|
-
'aria-pressed',
|
|
412
|
-
'true',
|
|
413
|
-
);
|
|
414
|
-
});
|
|
415
|
-
},
|
|
416
|
-
};
|
|
417
|
-
|
|
418
|
-
// 10. Edge Cases Tests
|
|
419
|
-
export const EdgeCases: Story = {
|
|
420
|
-
render: () => (
|
|
421
|
-
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
|
422
|
-
<Box>
|
|
423
|
-
<Typography variant="h6" gutterBottom>
|
|
424
|
-
Single Option
|
|
425
|
-
</Typography>
|
|
426
|
-
<ToggleGroup
|
|
427
|
-
options={[{ value: 'only', label: 'Only Option' }]}
|
|
428
|
-
data-testid="single-option"
|
|
429
|
-
/>
|
|
430
|
-
</Box>
|
|
431
|
-
|
|
432
|
-
<Box>
|
|
433
|
-
<Typography variant="h6" gutterBottom>
|
|
434
|
-
Empty Labels
|
|
435
|
-
</Typography>
|
|
436
|
-
<ToggleGroup
|
|
437
|
-
options={[
|
|
438
|
-
{ value: 'icon1', label: '', icon: <Heart size={16} /> },
|
|
439
|
-
{ value: 'icon2', label: '', icon: <Star size={16} /> },
|
|
440
|
-
]}
|
|
441
|
-
data-testid="empty-labels"
|
|
442
|
-
/>
|
|
443
|
-
</Box>
|
|
444
|
-
|
|
445
|
-
<Box>
|
|
446
|
-
<Typography variant="h6" gutterBottom>
|
|
447
|
-
Long Labels
|
|
448
|
-
</Typography>
|
|
449
|
-
<ToggleGroup
|
|
450
|
-
options={[
|
|
451
|
-
{ value: 'long1', label: 'This is a very long label that might wrap' },
|
|
452
|
-
{ value: 'long2', label: 'Another extremely long label for testing purposes' },
|
|
453
|
-
]}
|
|
454
|
-
data-testid="long-labels"
|
|
455
|
-
/>
|
|
456
|
-
</Box>
|
|
457
|
-
|
|
458
|
-
<Box>
|
|
459
|
-
<Typography variant="h6" gutterBottom>
|
|
460
|
-
All Disabled
|
|
461
|
-
</Typography>
|
|
462
|
-
<ToggleGroup
|
|
463
|
-
options={[
|
|
464
|
-
{ value: 'dis1', label: 'Disabled 1', disabled: true },
|
|
465
|
-
{ value: 'dis2', label: 'Disabled 2', disabled: true },
|
|
466
|
-
]}
|
|
467
|
-
data-testid="all-disabled"
|
|
468
|
-
/>
|
|
469
|
-
</Box>
|
|
470
|
-
</Box>
|
|
471
|
-
),
|
|
472
|
-
play: async ({ canvasElement }) => {
|
|
473
|
-
const canvas = within(canvasElement);
|
|
474
|
-
|
|
475
|
-
// Test single option
|
|
476
|
-
const singleOption = canvas.getByTestId('single-option');
|
|
477
|
-
const singleButtons = within(singleOption).getAllByRole('button');
|
|
478
|
-
expect(singleButtons).toHaveLength(1);
|
|
479
|
-
|
|
480
|
-
// Test empty labels (icon-only buttons)
|
|
481
|
-
const emptyLabels = canvas.getByTestId('empty-labels');
|
|
482
|
-
const emptyLabelButtons = within(emptyLabels).getAllByRole('button');
|
|
483
|
-
expect(emptyLabelButtons).toHaveLength(2);
|
|
484
|
-
|
|
485
|
-
// Test long labels
|
|
486
|
-
const longLabels = canvas.getByTestId('long-labels');
|
|
487
|
-
const longLabelButtons = within(longLabels).getAllByRole('button');
|
|
488
|
-
expect(longLabelButtons).toHaveLength(2);
|
|
489
|
-
|
|
490
|
-
// Test all disabled
|
|
491
|
-
const allDisabled = canvas.getByTestId('all-disabled');
|
|
492
|
-
const disabledButtons = within(allDisabled).getAllByRole('button');
|
|
493
|
-
expect(disabledButtons).toHaveLength(2);
|
|
494
|
-
disabledButtons.forEach((button) => {
|
|
495
|
-
expect(button).toBeDisabled();
|
|
496
|
-
});
|
|
497
|
-
},
|
|
498
|
-
};
|
|
499
|
-
|
|
500
|
-
// Component for controlled glow testing
|
|
501
|
-
const ControlledGlowTest = () => {
|
|
502
|
-
const [normalValue, setNormalValue] = React.useState<string>('');
|
|
503
|
-
const [glassValue, setGlassValue] = React.useState<string>('');
|
|
504
|
-
const [gradientValue, setGradientValue] = React.useState<string>('');
|
|
505
|
-
|
|
506
|
-
return (
|
|
507
|
-
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 4, p: 4, backgroundColor: '#f0f0f0' }}>
|
|
508
|
-
<Box>
|
|
509
|
-
<Typography variant="h6" gutterBottom>
|
|
510
|
-
Normal Toggle Group
|
|
511
|
-
</Typography>
|
|
512
|
-
<ToggleGroup
|
|
513
|
-
options={alignOptions}
|
|
514
|
-
data-testid="normal-group"
|
|
515
|
-
value={normalValue}
|
|
516
|
-
onChange={(_, newValue) => setNormalValue(newValue || '')}
|
|
517
|
-
/>
|
|
518
|
-
</Box>
|
|
519
|
-
|
|
520
|
-
<Box>
|
|
521
|
-
<Typography variant="h6" gutterBottom>
|
|
522
|
-
Glass Effect Toggle Group
|
|
523
|
-
</Typography>
|
|
524
|
-
<ToggleGroup
|
|
525
|
-
options={alignOptions}
|
|
526
|
-
glass
|
|
527
|
-
data-testid="glass-group"
|
|
528
|
-
value={glassValue}
|
|
529
|
-
onChange={(_, newValue) => setGlassValue(newValue || '')}
|
|
530
|
-
/>
|
|
531
|
-
</Box>
|
|
532
|
-
|
|
533
|
-
<Box>
|
|
534
|
-
<Typography variant="h6" gutterBottom>
|
|
535
|
-
Glass + Gradient Toggle Group
|
|
536
|
-
</Typography>
|
|
537
|
-
<ToggleGroup
|
|
538
|
-
options={themeOptions}
|
|
539
|
-
glass
|
|
540
|
-
gradient
|
|
541
|
-
color="secondary"
|
|
542
|
-
data-testid="glass-gradient-group"
|
|
543
|
-
value={gradientValue}
|
|
544
|
-
onChange={(_, newValue) => setGradientValue(newValue || '')}
|
|
545
|
-
/>
|
|
546
|
-
</Box>
|
|
547
|
-
</Box>
|
|
548
|
-
);
|
|
549
|
-
};
|
|
550
|
-
|
|
551
|
-
// 11. Glow Effect Tests
|
|
552
|
-
export const GlowEffectTest: Story = {
|
|
553
|
-
render: () => <ControlledGlowTest />,
|
|
554
|
-
play: async ({ canvasElement }) => {
|
|
555
|
-
const canvas = within(canvasElement);
|
|
556
|
-
|
|
557
|
-
// Test normal group (no glass)
|
|
558
|
-
const normalGroup = canvas.getByTestId('normal-group');
|
|
559
|
-
const normalStyles = window.getComputedStyle(normalGroup);
|
|
560
|
-
expect(normalStyles.backdropFilter).toBe('none');
|
|
561
|
-
// CSS transparent can be rendered as rgba(0, 0, 0, 0)
|
|
562
|
-
expect(normalStyles.backgroundColor).toMatch(/transparent|rgba\(0,\s*0,\s*0,\s*0\)/);
|
|
563
|
-
|
|
564
|
-
// Test glass effect group
|
|
565
|
-
const glassGroup = canvas.getByTestId('glass-group');
|
|
566
|
-
const glassStyles = window.getComputedStyle(glassGroup);
|
|
567
|
-
|
|
568
|
-
// Verify glass-specific styling
|
|
569
|
-
expect(glassStyles.backdropFilter).toContain('blur(20px)');
|
|
570
|
-
expect(glassStyles.backgroundColor).toContain('rgba');
|
|
571
|
-
expect(parseInt(glassStyles.padding)).toBe(4);
|
|
572
|
-
expect(glassStyles.borderRadius).not.toBe('0px');
|
|
573
|
-
expect(glassStyles.border).toContain('1px solid');
|
|
574
|
-
|
|
575
|
-
// Test glass + gradient combination
|
|
576
|
-
const glassGradientGroup = canvas.getByTestId('glass-gradient-group');
|
|
577
|
-
const glassGradientStyles = window.getComputedStyle(glassGradientGroup);
|
|
578
|
-
|
|
579
|
-
// Verify glass effect is still applied
|
|
580
|
-
expect(glassGradientStyles.backdropFilter).toContain('blur(20px)');
|
|
581
|
-
expect(glassGradientStyles.backgroundColor).toContain('rgba');
|
|
582
|
-
|
|
583
|
-
// Test interaction with glass effect
|
|
584
|
-
const glassButtons = within(glassGroup).getAllByRole('button');
|
|
585
|
-
|
|
586
|
-
// Click a button and verify glass effect is maintained
|
|
587
|
-
await userEvent.click(glassButtons[1]);
|
|
588
|
-
|
|
589
|
-
await waitFor(() => {
|
|
590
|
-
const updatedStyles = window.getComputedStyle(glassGroup);
|
|
591
|
-
expect(updatedStyles.backdropFilter).toContain('blur(20px)');
|
|
592
|
-
// For uncontrolled mode, check aria-pressed
|
|
593
|
-
expect(glassButtons[1]).toHaveAttribute('aria-pressed', 'true');
|
|
594
|
-
});
|
|
595
|
-
|
|
596
|
-
// Test that gradient effect works on selected button
|
|
597
|
-
const gradientButtons = within(glassGradientGroup).getAllByRole('button');
|
|
598
|
-
await userEvent.click(gradientButtons[0]);
|
|
599
|
-
|
|
600
|
-
await waitFor(() => {
|
|
601
|
-
const buttonStyles = window.getComputedStyle(gradientButtons[0]);
|
|
602
|
-
// Selected button should have gradient (linear-gradient in background)
|
|
603
|
-
expect(buttonStyles.background).toContain('linear-gradient');
|
|
604
|
-
});
|
|
605
|
-
},
|
|
606
|
-
};
|
|
607
|
-
|
|
608
|
-
// 12. Integration Tests
|
|
609
|
-
const IntegrationComponent = () => {
|
|
610
|
-
const [singleValue, setSingleValue] = React.useState<string>('');
|
|
611
|
-
const [multipleValue, setMultipleValue] = React.useState<string[]>([]);
|
|
612
|
-
|
|
613
|
-
return (
|
|
614
|
-
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
|
615
|
-
<Box>
|
|
616
|
-
<Typography variant="h6" gutterBottom>
|
|
617
|
-
Text Alignment
|
|
618
|
-
</Typography>
|
|
619
|
-
<ToggleGroup
|
|
620
|
-
variant="single"
|
|
621
|
-
options={alignOptions}
|
|
622
|
-
value={singleValue}
|
|
623
|
-
onChange={(_, value) => setSingleValue(value || '')}
|
|
624
|
-
data-testid="alignment-group"
|
|
625
|
-
/>
|
|
626
|
-
<Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}>
|
|
627
|
-
Selected: {singleValue || 'None'}
|
|
628
|
-
</Typography>
|
|
629
|
-
</Box>
|
|
630
|
-
|
|
631
|
-
<Box>
|
|
632
|
-
<Typography variant="h6" gutterBottom>
|
|
633
|
-
Text Formatting
|
|
634
|
-
</Typography>
|
|
635
|
-
<ToggleGroup
|
|
636
|
-
variant="multiple"
|
|
637
|
-
options={formatOptions}
|
|
638
|
-
value={multipleValue}
|
|
639
|
-
onChange={(_, value) => setMultipleValue(value || [])}
|
|
640
|
-
color="secondary"
|
|
641
|
-
data-testid="formatting-group"
|
|
642
|
-
/>
|
|
643
|
-
<Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}>
|
|
644
|
-
Selected: {multipleValue.join(', ') || 'None'}
|
|
645
|
-
</Typography>
|
|
646
|
-
</Box>
|
|
647
|
-
|
|
648
|
-
<Box>
|
|
649
|
-
<Typography variant="h6" gutterBottom>
|
|
650
|
-
Preview Text
|
|
651
|
-
</Typography>
|
|
652
|
-
<Typography
|
|
653
|
-
variant="body1"
|
|
654
|
-
sx={{
|
|
655
|
-
fontWeight: multipleValue.includes('bold') ? 'bold' : 'normal',
|
|
656
|
-
fontStyle: multipleValue.includes('italic') ? 'italic' : 'normal',
|
|
657
|
-
textDecoration: multipleValue.includes('underline') ? 'underline' : 'none',
|
|
658
|
-
textAlign: (singleValue as 'left' | 'center' | 'right' | undefined) || 'left',
|
|
659
|
-
border: 1,
|
|
660
|
-
borderColor: 'divider',
|
|
661
|
-
p: 2,
|
|
662
|
-
borderRadius: 1,
|
|
663
|
-
}}
|
|
664
|
-
data-testid="preview-text"
|
|
665
|
-
>
|
|
666
|
-
This is preview text showing the applied formatting and alignment.
|
|
667
|
-
</Typography>
|
|
668
|
-
</Box>
|
|
669
|
-
</Box>
|
|
670
|
-
);
|
|
671
|
-
};
|
|
672
|
-
|
|
673
|
-
export const Integration: Story = {
|
|
674
|
-
render: () => <IntegrationComponent />,
|
|
675
|
-
play: async ({ canvasElement }) => {
|
|
676
|
-
const canvas = within(canvasElement);
|
|
677
|
-
|
|
678
|
-
// Test alignment integration
|
|
679
|
-
const alignmentGroup = canvas.getByTestId('alignment-group');
|
|
680
|
-
const alignButtons = within(alignmentGroup).getAllByRole('button');
|
|
681
|
-
|
|
682
|
-
await userEvent.click(alignButtons[1]); // Center align
|
|
683
|
-
|
|
684
|
-
const previewText = canvas.getByTestId('preview-text');
|
|
685
|
-
await waitFor(() => {
|
|
686
|
-
const styles = window.getComputedStyle(previewText);
|
|
687
|
-
expect(styles.textAlign).toBe('center');
|
|
688
|
-
});
|
|
689
|
-
|
|
690
|
-
// Test formatting integration
|
|
691
|
-
const formattingGroup = canvas.getByTestId('formatting-group');
|
|
692
|
-
const formatButtons = within(formattingGroup).getAllByRole('button');
|
|
693
|
-
|
|
694
|
-
await userEvent.click(formatButtons[0]); // Bold
|
|
695
|
-
await waitFor(() => {
|
|
696
|
-
const styles = window.getComputedStyle(previewText);
|
|
697
|
-
expect(styles.fontWeight).toBe('700');
|
|
698
|
-
});
|
|
699
|
-
|
|
700
|
-
await userEvent.click(formatButtons[1]); // Italic
|
|
701
|
-
await waitFor(() => {
|
|
702
|
-
const styles = window.getComputedStyle(previewText);
|
|
703
|
-
expect(styles.fontStyle).toBe('italic');
|
|
704
|
-
});
|
|
705
|
-
},
|
|
706
|
-
};
|
|
707
|
-
|
|
708
|
-
// 13. TestId Tests
|
|
709
|
-
export const TestIds: Story = {
|
|
710
|
-
render: () => {
|
|
711
|
-
const TestIdComponent = () => {
|
|
712
|
-
const [defaultValue, setDefaultValue] = React.useState<string>('');
|
|
713
|
-
const [customValue, setCustomValue] = React.useState<string>('');
|
|
714
|
-
const [iconValue, setIconValue] = React.useState<string>('');
|
|
715
|
-
const [disabledValue, setDisabledValue] = React.useState<string>('');
|
|
716
|
-
|
|
717
|
-
return (
|
|
718
|
-
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
|
719
|
-
<Box>
|
|
720
|
-
<Typography variant="h6" gutterBottom>
|
|
721
|
-
Default TestId
|
|
722
|
-
</Typography>
|
|
723
|
-
<ToggleGroup
|
|
724
|
-
options={alignOptions}
|
|
725
|
-
value={defaultValue}
|
|
726
|
-
onChange={(_, val) => setDefaultValue(val || '')}
|
|
727
|
-
/>
|
|
728
|
-
</Box>
|
|
729
|
-
|
|
730
|
-
<Box>
|
|
731
|
-
<Typography variant="h6" gutterBottom>
|
|
732
|
-
Custom TestId
|
|
733
|
-
</Typography>
|
|
734
|
-
<ToggleGroup
|
|
735
|
-
options={formatOptions}
|
|
736
|
-
dataTestId="custom-toggle"
|
|
737
|
-
value={customValue}
|
|
738
|
-
onChange={(_, val) => setCustomValue(val || '')}
|
|
739
|
-
/>
|
|
740
|
-
</Box>
|
|
741
|
-
|
|
742
|
-
<Box>
|
|
743
|
-
<Typography variant="h6" gutterBottom>
|
|
744
|
-
TestId with Icons
|
|
745
|
-
</Typography>
|
|
746
|
-
<ToggleGroup
|
|
747
|
-
options={themeOptions}
|
|
748
|
-
dataTestId="icon-toggle"
|
|
749
|
-
value={iconValue}
|
|
750
|
-
onChange={(_, val) => setIconValue(val || '')}
|
|
751
|
-
/>
|
|
752
|
-
</Box>
|
|
753
|
-
|
|
754
|
-
<Box>
|
|
755
|
-
<Typography variant="h6" gutterBottom>
|
|
756
|
-
TestId with Disabled Options
|
|
757
|
-
</Typography>
|
|
758
|
-
<ToggleGroup
|
|
759
|
-
options={optionsWithDisabled}
|
|
760
|
-
dataTestId="disabled-toggle"
|
|
761
|
-
value={disabledValue}
|
|
762
|
-
onChange={(_, val) => setDisabledValue(val || '')}
|
|
763
|
-
/>
|
|
764
|
-
</Box>
|
|
765
|
-
</Box>
|
|
766
|
-
);
|
|
767
|
-
};
|
|
768
|
-
|
|
769
|
-
return <TestIdComponent />;
|
|
770
|
-
},
|
|
771
|
-
play: async ({ canvasElement }) => {
|
|
772
|
-
const canvas = within(canvasElement);
|
|
773
|
-
|
|
774
|
-
// Test default testId
|
|
775
|
-
const defaultGroup = canvas.getByTestId('toggle-group');
|
|
776
|
-
expect(defaultGroup).toBeInTheDocument();
|
|
777
|
-
|
|
778
|
-
// Test default item testIds
|
|
779
|
-
expect(canvas.getByTestId('toggle-group-item-left')).toBeInTheDocument();
|
|
780
|
-
expect(canvas.getByTestId('toggle-group-item-center')).toBeInTheDocument();
|
|
781
|
-
expect(canvas.getByTestId('toggle-group-item-right')).toBeInTheDocument();
|
|
782
|
-
|
|
783
|
-
// Test custom testId
|
|
784
|
-
const customGroup = canvas.getByTestId('custom-toggle');
|
|
785
|
-
expect(customGroup).toBeInTheDocument();
|
|
786
|
-
|
|
787
|
-
// Test custom item testIds
|
|
788
|
-
expect(canvas.getByTestId('custom-toggle-item-bold')).toBeInTheDocument();
|
|
789
|
-
expect(canvas.getByTestId('custom-toggle-item-italic')).toBeInTheDocument();
|
|
790
|
-
expect(canvas.getByTestId('custom-toggle-item-underline')).toBeInTheDocument();
|
|
791
|
-
|
|
792
|
-
// Test testIds with icons
|
|
793
|
-
const iconGroup = canvas.getByTestId('icon-toggle');
|
|
794
|
-
expect(iconGroup).toBeInTheDocument();
|
|
795
|
-
expect(canvas.getByTestId('icon-toggle-item-light')).toBeInTheDocument();
|
|
796
|
-
expect(canvas.getByTestId('icon-toggle-item-dark')).toBeInTheDocument();
|
|
797
|
-
expect(canvas.getByTestId('icon-toggle-item-system')).toBeInTheDocument();
|
|
798
|
-
|
|
799
|
-
// Test testIds with disabled options
|
|
800
|
-
const disabledGroup = canvas.getByTestId('disabled-toggle');
|
|
801
|
-
expect(disabledGroup).toBeInTheDocument();
|
|
802
|
-
|
|
803
|
-
const enabledItem = canvas.getByTestId('disabled-toggle-item-option1');
|
|
804
|
-
const disabledItem = canvas.getByTestId('disabled-toggle-item-option2');
|
|
805
|
-
const anotherEnabledItem = canvas.getByTestId('disabled-toggle-item-option3');
|
|
806
|
-
|
|
807
|
-
expect(enabledItem).not.toBeDisabled();
|
|
808
|
-
expect(disabledItem).toBeDisabled();
|
|
809
|
-
expect(anotherEnabledItem).not.toBeDisabled();
|
|
810
|
-
|
|
811
|
-
// Test interaction with testIds
|
|
812
|
-
await userEvent.click(enabledItem);
|
|
813
|
-
await waitFor(() => {
|
|
814
|
-
expect(enabledItem).toHaveAttribute('aria-pressed', 'true');
|
|
815
|
-
});
|
|
816
|
-
|
|
817
|
-
// Verify disabled item remains disabled and cannot be interacted with
|
|
818
|
-
// Note: We don't attempt to click disabled items as they have pointer-events: none
|
|
819
|
-
await waitFor(() => {
|
|
820
|
-
expect(disabledItem).toHaveAttribute('aria-pressed', 'false');
|
|
821
|
-
expect(disabledItem).toBeDisabled();
|
|
822
|
-
});
|
|
823
|
-
},
|
|
824
|
-
};
|
|
825
|
-
|
|
826
|
-
// Component for controlled testId testing
|
|
827
|
-
const ControlledTestIdComponent = () => {
|
|
828
|
-
const [value, setValue] = React.useState<string>('');
|
|
829
|
-
|
|
830
|
-
return (
|
|
831
|
-
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
|
832
|
-
<Box>
|
|
833
|
-
<Typography variant="h6" gutterBottom>
|
|
834
|
-
Controlled Toggle with TestId
|
|
835
|
-
</Typography>
|
|
836
|
-
<ToggleGroup
|
|
837
|
-
variant="single"
|
|
838
|
-
options={alignOptions}
|
|
839
|
-
value={value}
|
|
840
|
-
onChange={(_, newValue) => setValue(newValue || '')}
|
|
841
|
-
dataTestId="controlled-toggle"
|
|
842
|
-
/>
|
|
843
|
-
<Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}>
|
|
844
|
-
Selected: {value || 'None'}
|
|
845
|
-
</Typography>
|
|
846
|
-
</Box>
|
|
847
|
-
</Box>
|
|
848
|
-
);
|
|
849
|
-
};
|
|
850
|
-
|
|
851
|
-
// 14. TestId Controlled Component Test
|
|
852
|
-
export const TestIdControlled: Story = {
|
|
853
|
-
render: () => <ControlledTestIdComponent />,
|
|
854
|
-
play: async ({ canvasElement }) => {
|
|
855
|
-
const canvas = within(canvasElement);
|
|
856
|
-
|
|
857
|
-
// Test controlled component with testIds
|
|
858
|
-
const group = canvas.getByTestId('controlled-toggle');
|
|
859
|
-
expect(group).toBeInTheDocument();
|
|
860
|
-
|
|
861
|
-
// Test items are accessible by testId
|
|
862
|
-
const leftButton = canvas.getByTestId('controlled-toggle-item-left');
|
|
863
|
-
const centerButton = canvas.getByTestId('controlled-toggle-item-center');
|
|
864
|
-
const rightButton = canvas.getByTestId('controlled-toggle-item-right');
|
|
865
|
-
|
|
866
|
-
expect(leftButton).toBeInTheDocument();
|
|
867
|
-
expect(centerButton).toBeInTheDocument();
|
|
868
|
-
expect(rightButton).toBeInTheDocument();
|
|
869
|
-
|
|
870
|
-
// Test clicking via testId updates state
|
|
871
|
-
await userEvent.click(leftButton);
|
|
872
|
-
await waitFor(() => {
|
|
873
|
-
expect(leftButton).toHaveAttribute('aria-pressed', 'true');
|
|
874
|
-
});
|
|
875
|
-
|
|
876
|
-
// Test clicking another button
|
|
877
|
-
await userEvent.click(centerButton);
|
|
878
|
-
await waitFor(() => {
|
|
879
|
-
expect(centerButton).toHaveAttribute('aria-pressed', 'true');
|
|
880
|
-
expect(leftButton).toHaveAttribute('aria-pressed', 'false');
|
|
881
|
-
});
|
|
882
|
-
|
|
883
|
-
// Test clicking the same button deselects in single mode
|
|
884
|
-
await userEvent.click(centerButton);
|
|
885
|
-
await waitFor(() => {
|
|
886
|
-
expect(centerButton).toHaveAttribute('aria-pressed', 'false');
|
|
887
|
-
});
|
|
888
|
-
},
|
|
889
|
-
};
|
|
890
|
-
|
|
891
|
-
// 15. TestId with Special Characters
|
|
892
|
-
export const TestIdSpecialCharacters: Story = {
|
|
893
|
-
args: {
|
|
894
|
-
options: [
|
|
895
|
-
{ value: 'option-with-dash', label: 'With Dash' },
|
|
896
|
-
{ value: 'option_with_underscore', label: 'With Underscore' },
|
|
897
|
-
{ value: 'option.with.dots', label: 'With Dots' },
|
|
898
|
-
{ value: 'option123', label: 'With Numbers' },
|
|
899
|
-
],
|
|
900
|
-
dataTestId: 'special-chars-toggle',
|
|
901
|
-
},
|
|
902
|
-
play: async ({ canvasElement }) => {
|
|
903
|
-
const canvas = within(canvasElement);
|
|
904
|
-
|
|
905
|
-
// Test group testId
|
|
906
|
-
const group = canvas.getByTestId('special-chars-toggle');
|
|
907
|
-
expect(group).toBeInTheDocument();
|
|
908
|
-
|
|
909
|
-
// Test items with special characters in values
|
|
910
|
-
expect(canvas.getByTestId('special-chars-toggle-item-option-with-dash')).toBeInTheDocument();
|
|
911
|
-
expect(canvas.getByTestId('special-chars-toggle-item-option_with_underscore')).toBeInTheDocument();
|
|
912
|
-
expect(canvas.getByTestId('special-chars-toggle-item-option.with.dots')).toBeInTheDocument();
|
|
913
|
-
expect(canvas.getByTestId('special-chars-toggle-item-option123')).toBeInTheDocument();
|
|
914
|
-
},
|
|
915
|
-
};
|