@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,834 +0,0 @@
|
|
|
1
|
-
/* eslint-env browser */
|
|
2
|
-
import { Box, Button, Stack,TextField, Typography } from '@mui/material';
|
|
3
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
|
-
import { useEffect, useRef,useState } from 'react';
|
|
5
|
-
import { expect, userEvent, waitFor,within } from 'storybook/test';
|
|
6
|
-
|
|
7
|
-
import { Toast, ToastContainer,ToastProvider, useToast } from './Toast';
|
|
8
|
-
|
|
9
|
-
// Toast component test stories
|
|
10
|
-
const meta: Meta<typeof Toast> = {
|
|
11
|
-
title: 'Feedback/Toast/Tests',
|
|
12
|
-
component: Toast,
|
|
13
|
-
parameters: {
|
|
14
|
-
layout: 'centered',
|
|
15
|
-
chromatic: { disableSnapshot: false },
|
|
16
|
-
},
|
|
17
|
-
tags: ['autodocs', 'test', 'component:Toast'],
|
|
18
|
-
decorators: [
|
|
19
|
-
(Story) => (
|
|
20
|
-
<ToastProvider>
|
|
21
|
-
<Story />
|
|
22
|
-
<ToastContainer />
|
|
23
|
-
</ToastProvider>
|
|
24
|
-
),
|
|
25
|
-
],
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export default meta;
|
|
29
|
-
type Story = StoryObj<typeof meta>;
|
|
30
|
-
|
|
31
|
-
// Basic Interaction Tests
|
|
32
|
-
export const BasicInteraction: Story = {
|
|
33
|
-
render: function BasicInteractionTest() {
|
|
34
|
-
const { addToast, removeToast, clearAllToasts } = useToast();
|
|
35
|
-
const [toastId, setToastId] = useState<string | null>(null);
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<Stack spacing={2} sx={{ minWidth: 300 }}>
|
|
39
|
-
<Typography variant="h6">Basic Interaction Test</Typography>
|
|
40
|
-
<Button
|
|
41
|
-
data-testid="add-toast"
|
|
42
|
-
onClick={() => {
|
|
43
|
-
const id = addToast({
|
|
44
|
-
message: 'Test toast message',
|
|
45
|
-
variant: 'info',
|
|
46
|
-
duration: 10000,
|
|
47
|
-
});
|
|
48
|
-
setToastId(id);
|
|
49
|
-
}}
|
|
50
|
-
>
|
|
51
|
-
Add Toast
|
|
52
|
-
</Button>
|
|
53
|
-
<Button
|
|
54
|
-
data-testid="remove-toast"
|
|
55
|
-
onClick={() => {
|
|
56
|
-
if (toastId) removeToast(toastId);
|
|
57
|
-
}}
|
|
58
|
-
disabled={!toastId}
|
|
59
|
-
>
|
|
60
|
-
Remove Toast
|
|
61
|
-
</Button>
|
|
62
|
-
<Button data-testid="clear-all" onClick={clearAllToasts}>
|
|
63
|
-
Clear All
|
|
64
|
-
</Button>
|
|
65
|
-
</Stack>
|
|
66
|
-
);
|
|
67
|
-
},
|
|
68
|
-
play: async ({ canvasElement }) => {
|
|
69
|
-
const canvas = within(canvasElement);
|
|
70
|
-
const addButton = canvas.getByTestId('add-toast');
|
|
71
|
-
const removeButton = canvas.getByTestId('remove-toast');
|
|
72
|
-
|
|
73
|
-
// Test adding toast
|
|
74
|
-
await userEvent.click(addButton);
|
|
75
|
-
await waitFor(() => {
|
|
76
|
-
const toastElement = document.querySelector('[role="alert"]');
|
|
77
|
-
expect(toastElement).toBeInTheDocument();
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
// Test removing toast
|
|
81
|
-
await userEvent.click(removeButton);
|
|
82
|
-
await waitFor(
|
|
83
|
-
() => {
|
|
84
|
-
const toastElement = document.querySelector('[role="alert"]');
|
|
85
|
-
expect(toastElement).not.toBeInTheDocument();
|
|
86
|
-
},
|
|
87
|
-
{ timeout: 1000 },
|
|
88
|
-
);
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
// Form Interaction Tests
|
|
93
|
-
export const FormInteraction: Story = {
|
|
94
|
-
render: function FormInteractionTest() {
|
|
95
|
-
const { addToast } = useToast();
|
|
96
|
-
const [message, setMessage] = useState('');
|
|
97
|
-
const [variant, setVariant] = useState<'success' | 'error' | 'warning' | 'info'>('info');
|
|
98
|
-
|
|
99
|
-
const handleSubmit = (e: React.FormEvent) => {
|
|
100
|
-
e.preventDefault();
|
|
101
|
-
if (message.trim()) {
|
|
102
|
-
addToast({
|
|
103
|
-
message,
|
|
104
|
-
variant,
|
|
105
|
-
action: {
|
|
106
|
-
label: 'Undo',
|
|
107
|
-
onClick: () => addToast({ message: 'Action undone', variant: 'success' }),
|
|
108
|
-
},
|
|
109
|
-
});
|
|
110
|
-
setMessage('');
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
return (
|
|
115
|
-
<Box component="form" onSubmit={handleSubmit} sx={{ minWidth: 300 }}>
|
|
116
|
-
<Stack spacing={2}>
|
|
117
|
-
<Typography variant="h6">Form Interaction Test</Typography>
|
|
118
|
-
<TextField
|
|
119
|
-
data-testid="message-input"
|
|
120
|
-
label="Toast Message"
|
|
121
|
-
value={message}
|
|
122
|
-
onChange={(e) => setMessage(e.target.value)}
|
|
123
|
-
fullWidth
|
|
124
|
-
/>
|
|
125
|
-
<TextField
|
|
126
|
-
data-testid="variant-select"
|
|
127
|
-
select
|
|
128
|
-
label="Variant"
|
|
129
|
-
value={variant}
|
|
130
|
-
onChange={(e) => setVariant(e.target.value as 'success' | 'error' | 'warning' | 'info')}
|
|
131
|
-
SelectProps={{ native: true }}
|
|
132
|
-
>
|
|
133
|
-
<option value="info">Info</option>
|
|
134
|
-
<option value="success">Success</option>
|
|
135
|
-
<option value="warning">Warning</option>
|
|
136
|
-
<option value="error">Error</option>
|
|
137
|
-
</TextField>
|
|
138
|
-
<Button
|
|
139
|
-
data-testid="submit-form"
|
|
140
|
-
type="submit"
|
|
141
|
-
variant="contained"
|
|
142
|
-
disabled={!message.trim()}
|
|
143
|
-
>
|
|
144
|
-
Show Toast
|
|
145
|
-
</Button>
|
|
146
|
-
</Stack>
|
|
147
|
-
</Box>
|
|
148
|
-
);
|
|
149
|
-
},
|
|
150
|
-
play: async ({ canvasElement }) => {
|
|
151
|
-
const canvas = within(canvasElement);
|
|
152
|
-
|
|
153
|
-
// Get input and button
|
|
154
|
-
const messageInput = canvas.getByLabelText('Toast Message') as HTMLInputElement;
|
|
155
|
-
const submitButton = canvas.getByTestId('submit-form');
|
|
156
|
-
|
|
157
|
-
// Initially button should be disabled (no message)
|
|
158
|
-
expect(submitButton).toBeDisabled();
|
|
159
|
-
|
|
160
|
-
// Type message to enable button
|
|
161
|
-
await userEvent.type(messageInput, 'Test form message');
|
|
162
|
-
|
|
163
|
-
// Wait a bit for React state to update
|
|
164
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
165
|
-
|
|
166
|
-
// Button should now be enabled
|
|
167
|
-
expect(submitButton).not.toBeDisabled();
|
|
168
|
-
|
|
169
|
-
// Click to submit
|
|
170
|
-
await userEvent.click(submitButton);
|
|
171
|
-
|
|
172
|
-
// Wait for toast to appear
|
|
173
|
-
await waitFor(() => {
|
|
174
|
-
const toastElement = document.querySelector('[role="alert"]');
|
|
175
|
-
expect(toastElement).toBeInTheDocument();
|
|
176
|
-
expect(toastElement).toHaveTextContent('Test form message');
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// Verify action button exists
|
|
180
|
-
const actionButton = document.querySelector('[role="alert"] button:not([aria-label="close"])');
|
|
181
|
-
expect(actionButton).toBeInTheDocument();
|
|
182
|
-
expect(actionButton).toHaveTextContent('Undo');
|
|
183
|
-
},
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
// Keyboard Navigation Tests
|
|
187
|
-
export const KeyboardNavigation: Story = {
|
|
188
|
-
render: function KeyboardNavigationTest() {
|
|
189
|
-
const { addToast } = useToast();
|
|
190
|
-
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
191
|
-
|
|
192
|
-
useEffect(() => {
|
|
193
|
-
// Auto-focus for keyboard testing
|
|
194
|
-
if (buttonRef.current) {
|
|
195
|
-
buttonRef.current.focus();
|
|
196
|
-
}
|
|
197
|
-
}, []);
|
|
198
|
-
|
|
199
|
-
return (
|
|
200
|
-
<Stack spacing={2} sx={{ minWidth: 300 }}>
|
|
201
|
-
<Typography variant="h6">Keyboard Navigation Test</Typography>
|
|
202
|
-
<Button
|
|
203
|
-
ref={buttonRef}
|
|
204
|
-
data-testid="keyboard-trigger"
|
|
205
|
-
onClick={() =>
|
|
206
|
-
addToast({
|
|
207
|
-
message: 'Press Tab to navigate to close button, then Enter to close',
|
|
208
|
-
variant: 'info',
|
|
209
|
-
persistent: true,
|
|
210
|
-
})
|
|
211
|
-
}
|
|
212
|
-
onKeyDown={(e) => {
|
|
213
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
214
|
-
e.preventDefault();
|
|
215
|
-
addToast({
|
|
216
|
-
message: 'Toast triggered by keyboard',
|
|
217
|
-
variant: 'success',
|
|
218
|
-
closable: true,
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
}}
|
|
222
|
-
>
|
|
223
|
-
Trigger Toast (Enter/Space)
|
|
224
|
-
</Button>
|
|
225
|
-
</Stack>
|
|
226
|
-
);
|
|
227
|
-
},
|
|
228
|
-
play: async ({ canvasElement }) => {
|
|
229
|
-
const canvas = within(canvasElement);
|
|
230
|
-
const triggerButton = canvas.getByTestId('keyboard-trigger');
|
|
231
|
-
|
|
232
|
-
// Test keyboard activation
|
|
233
|
-
triggerButton.focus();
|
|
234
|
-
await userEvent.keyboard('{Enter}');
|
|
235
|
-
|
|
236
|
-
await waitFor(() => {
|
|
237
|
-
const toastElement = document.querySelector('[role="alert"]');
|
|
238
|
-
expect(toastElement).toBeInTheDocument();
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
// Test tab navigation to close button
|
|
242
|
-
await userEvent.keyboard('{Tab}');
|
|
243
|
-
const closeButton = document.querySelector('[aria-label="close"]');
|
|
244
|
-
if (closeButton) {
|
|
245
|
-
expect(closeButton).toHaveFocus();
|
|
246
|
-
await userEvent.keyboard('{Enter}');
|
|
247
|
-
|
|
248
|
-
await waitFor(
|
|
249
|
-
() => {
|
|
250
|
-
const toastElement = document.querySelector('[role="alert"]');
|
|
251
|
-
expect(toastElement).not.toBeInTheDocument();
|
|
252
|
-
},
|
|
253
|
-
{ timeout: 1000 },
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
},
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
// Screen Reader Tests
|
|
260
|
-
export const ScreenReader: Story = {
|
|
261
|
-
render: function ScreenReaderTest() {
|
|
262
|
-
const { addToast } = useToast();
|
|
263
|
-
|
|
264
|
-
return (
|
|
265
|
-
<Stack spacing={2} sx={{ minWidth: 300 }}>
|
|
266
|
-
<Typography variant="h6">Screen Reader Test</Typography>
|
|
267
|
-
<Button
|
|
268
|
-
data-testid="sr-info"
|
|
269
|
-
onClick={() =>
|
|
270
|
-
addToast({
|
|
271
|
-
message: 'Information for screen readers',
|
|
272
|
-
variant: 'info',
|
|
273
|
-
})
|
|
274
|
-
}
|
|
275
|
-
>
|
|
276
|
-
Info Toast
|
|
277
|
-
</Button>
|
|
278
|
-
<Button
|
|
279
|
-
data-testid="sr-error"
|
|
280
|
-
onClick={() =>
|
|
281
|
-
addToast({
|
|
282
|
-
message: 'Error message with proper ARIA',
|
|
283
|
-
variant: 'error',
|
|
284
|
-
})
|
|
285
|
-
}
|
|
286
|
-
>
|
|
287
|
-
Error Toast
|
|
288
|
-
</Button>
|
|
289
|
-
<Button
|
|
290
|
-
data-testid="sr-success"
|
|
291
|
-
onClick={() =>
|
|
292
|
-
addToast({
|
|
293
|
-
message: 'Success announcement',
|
|
294
|
-
variant: 'success',
|
|
295
|
-
})
|
|
296
|
-
}
|
|
297
|
-
>
|
|
298
|
-
Success Toast
|
|
299
|
-
</Button>
|
|
300
|
-
</Stack>
|
|
301
|
-
);
|
|
302
|
-
},
|
|
303
|
-
play: async ({ canvasElement }) => {
|
|
304
|
-
const canvas = within(canvasElement);
|
|
305
|
-
const infoButton = canvas.getByTestId('sr-info');
|
|
306
|
-
|
|
307
|
-
await userEvent.click(infoButton);
|
|
308
|
-
|
|
309
|
-
await waitFor(() => {
|
|
310
|
-
const toastElement = document.querySelector('[role="alert"]');
|
|
311
|
-
expect(toastElement).toBeInTheDocument();
|
|
312
|
-
expect(toastElement).toHaveAttribute('role', 'alert');
|
|
313
|
-
|
|
314
|
-
// Check for proper ARIA attributes
|
|
315
|
-
const alertContent = toastElement?.textContent;
|
|
316
|
-
expect(alertContent).toContain('Information for screen readers');
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
// Test close button accessibility
|
|
320
|
-
const closeButton = document.querySelector('[aria-label="close"]');
|
|
321
|
-
if (closeButton) {
|
|
322
|
-
expect(closeButton).toHaveAttribute('aria-label', 'close');
|
|
323
|
-
}
|
|
324
|
-
},
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
// Focus Management Tests
|
|
328
|
-
export const FocusManagement: Story = {
|
|
329
|
-
render: function FocusManagementTest() {
|
|
330
|
-
const { addToast } = useToast();
|
|
331
|
-
const triggerButtonRef = useRef<HTMLButtonElement>(null);
|
|
332
|
-
|
|
333
|
-
return (
|
|
334
|
-
<Stack spacing={2} sx={{ minWidth: 300 }}>
|
|
335
|
-
<Typography variant="h6">Focus Management Test</Typography>
|
|
336
|
-
<Button
|
|
337
|
-
ref={triggerButtonRef}
|
|
338
|
-
data-testid="focus-trigger"
|
|
339
|
-
onClick={() => {
|
|
340
|
-
addToast({
|
|
341
|
-
message: 'Focus should return to trigger after close',
|
|
342
|
-
variant: 'info',
|
|
343
|
-
action: {
|
|
344
|
-
label: 'Action',
|
|
345
|
-
onClick: () => {
|
|
346
|
-
/* Action clicked */
|
|
347
|
-
},
|
|
348
|
-
},
|
|
349
|
-
});
|
|
350
|
-
}}
|
|
351
|
-
>
|
|
352
|
-
Trigger Toast with Action
|
|
353
|
-
</Button>
|
|
354
|
-
<TextField
|
|
355
|
-
data-testid="focus-target"
|
|
356
|
-
label="Focus target"
|
|
357
|
-
placeholder="Tab here to test focus order"
|
|
358
|
-
/>
|
|
359
|
-
</Stack>
|
|
360
|
-
);
|
|
361
|
-
},
|
|
362
|
-
play: async ({ canvasElement }) => {
|
|
363
|
-
const canvas = within(canvasElement);
|
|
364
|
-
const triggerButton = canvas.getByTestId('focus-trigger');
|
|
365
|
-
const focusTarget = canvas.getByTestId('focus-target');
|
|
366
|
-
|
|
367
|
-
// Focus trigger and activate
|
|
368
|
-
triggerButton.focus();
|
|
369
|
-
await userEvent.click(triggerButton);
|
|
370
|
-
|
|
371
|
-
await waitFor(() => {
|
|
372
|
-
const toastElement = document.querySelector('[role="alert"]');
|
|
373
|
-
expect(toastElement).toBeInTheDocument();
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
// Wait for toast to be fully rendered with action button
|
|
377
|
-
await waitFor(() => {
|
|
378
|
-
const actionButton = document.querySelector(
|
|
379
|
-
'[role="alert"] button:not([aria-label="close"])',
|
|
380
|
-
);
|
|
381
|
-
expect(actionButton).toBeInTheDocument();
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
// Simplified focus test - just verify action button is focusable
|
|
385
|
-
await waitFor(
|
|
386
|
-
() => {
|
|
387
|
-
const actionButton = document.querySelector(
|
|
388
|
-
'[role="alert"] button:not([aria-label="close"])',
|
|
389
|
-
);
|
|
390
|
-
if (actionButton) {
|
|
391
|
-
// Test that we can focus the action button
|
|
392
|
-
(actionButton as HTMLElement).focus();
|
|
393
|
-
expect(actionButton).toHaveFocus();
|
|
394
|
-
}
|
|
395
|
-
},
|
|
396
|
-
{ timeout: 1000 },
|
|
397
|
-
);
|
|
398
|
-
|
|
399
|
-
// Test basic tab navigation works
|
|
400
|
-
const focusTargetInput = focusTarget.querySelector('input') as HTMLElement;
|
|
401
|
-
if (focusTargetInput) {
|
|
402
|
-
focusTargetInput.focus();
|
|
403
|
-
expect(focusTargetInput).toHaveFocus();
|
|
404
|
-
}
|
|
405
|
-
},
|
|
406
|
-
};
|
|
407
|
-
|
|
408
|
-
// Responsive Design Tests
|
|
409
|
-
export const ResponsiveDesign: Story = {
|
|
410
|
-
render: function ResponsiveDesignTest() {
|
|
411
|
-
const { addToast } = useToast();
|
|
412
|
-
|
|
413
|
-
return (
|
|
414
|
-
<Stack spacing={2} sx={{ minWidth: 300 }}>
|
|
415
|
-
<Typography variant="h6">Responsive Design Test</Typography>
|
|
416
|
-
<Button
|
|
417
|
-
data-testid="responsive-toast"
|
|
418
|
-
onClick={() => {
|
|
419
|
-
addToast({
|
|
420
|
-
message: 'This toast should adapt to different screen sizes and orientations',
|
|
421
|
-
variant: 'info',
|
|
422
|
-
duration: 8000,
|
|
423
|
-
});
|
|
424
|
-
}}
|
|
425
|
-
>
|
|
426
|
-
Show Responsive Toast
|
|
427
|
-
</Button>
|
|
428
|
-
<Typography variant="body2" color="text.secondary">
|
|
429
|
-
Resize viewport to test responsiveness
|
|
430
|
-
</Typography>
|
|
431
|
-
</Stack>
|
|
432
|
-
);
|
|
433
|
-
},
|
|
434
|
-
parameters: {
|
|
435
|
-
viewport: {
|
|
436
|
-
viewports: {
|
|
437
|
-
mobile: { name: 'Mobile', styles: { width: '375px', height: '667px' } },
|
|
438
|
-
tablet: { name: 'Tablet', styles: { width: '768px', height: '1024px' } },
|
|
439
|
-
desktop: { name: 'Desktop', styles: { width: '1024px', height: '768px' } },
|
|
440
|
-
},
|
|
441
|
-
},
|
|
442
|
-
},
|
|
443
|
-
play: async ({ canvasElement }) => {
|
|
444
|
-
const canvas = within(canvasElement);
|
|
445
|
-
const toastButton = canvas.getByTestId('responsive-toast');
|
|
446
|
-
|
|
447
|
-
await userEvent.click(toastButton);
|
|
448
|
-
|
|
449
|
-
await waitFor(() => {
|
|
450
|
-
const toastElement = document.querySelector('[role="alert"]');
|
|
451
|
-
expect(toastElement).toBeInTheDocument();
|
|
452
|
-
|
|
453
|
-
// Verify toast is positioned correctly and visible
|
|
454
|
-
const rect = toastElement?.getBoundingClientRect();
|
|
455
|
-
if (rect) {
|
|
456
|
-
expect(rect.width).toBeGreaterThan(0);
|
|
457
|
-
expect(rect.height).toBeGreaterThan(0);
|
|
458
|
-
}
|
|
459
|
-
});
|
|
460
|
-
},
|
|
461
|
-
};
|
|
462
|
-
|
|
463
|
-
// Theme Variations Tests
|
|
464
|
-
export const ThemeVariations: Story = {
|
|
465
|
-
render: function ThemeVariationsTest() {
|
|
466
|
-
const { addToast } = useToast();
|
|
467
|
-
|
|
468
|
-
return (
|
|
469
|
-
<Stack spacing={2} sx={{ minWidth: 300 }}>
|
|
470
|
-
<Typography variant="h6">Theme Variations Test</Typography>
|
|
471
|
-
<Button
|
|
472
|
-
data-testid="theme-toast"
|
|
473
|
-
onClick={() => {
|
|
474
|
-
addToast({ message: 'Default theme toast', variant: 'default' });
|
|
475
|
-
window.setTimeout(
|
|
476
|
-
() => addToast({ message: 'Glass effect toast', variant: 'success', glass: true }),
|
|
477
|
-
500,
|
|
478
|
-
);
|
|
479
|
-
}}
|
|
480
|
-
>
|
|
481
|
-
Show Theme Variations
|
|
482
|
-
</Button>
|
|
483
|
-
<Typography variant="body2" color="text.secondary">
|
|
484
|
-
Toggle theme to test light/dark mode
|
|
485
|
-
</Typography>
|
|
486
|
-
</Stack>
|
|
487
|
-
);
|
|
488
|
-
},
|
|
489
|
-
play: async ({ canvasElement }) => {
|
|
490
|
-
const canvas = within(canvasElement);
|
|
491
|
-
const themeButton = canvas.getByTestId('theme-toast');
|
|
492
|
-
|
|
493
|
-
await userEvent.click(themeButton);
|
|
494
|
-
|
|
495
|
-
await waitFor(() => {
|
|
496
|
-
const toastElements = document.querySelectorAll('[role="alert"]');
|
|
497
|
-
expect(toastElements.length).toBeGreaterThanOrEqual(1);
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
// Verify themed styling is applied
|
|
501
|
-
await waitFor(() => {
|
|
502
|
-
const toastElement = document.querySelector('[role="alert"]');
|
|
503
|
-
if (toastElement) {
|
|
504
|
-
const computedStyle = window.getComputedStyle(toastElement);
|
|
505
|
-
expect(computedStyle.borderRadius).toBeTruthy();
|
|
506
|
-
}
|
|
507
|
-
});
|
|
508
|
-
},
|
|
509
|
-
};
|
|
510
|
-
|
|
511
|
-
// Visual States Tests
|
|
512
|
-
export const VisualStates: Story = {
|
|
513
|
-
render: function VisualStatesTest() {
|
|
514
|
-
const { addToast } = useToast();
|
|
515
|
-
|
|
516
|
-
return (
|
|
517
|
-
<Stack spacing={2} sx={{ minWidth: 300 }}>
|
|
518
|
-
<Typography variant="h6">Visual States Test</Typography>
|
|
519
|
-
<Button
|
|
520
|
-
data-testid="all-variants"
|
|
521
|
-
onClick={() => {
|
|
522
|
-
const variants = ['default', 'success', 'error', 'warning', 'info'] as const;
|
|
523
|
-
variants.forEach((variant, index) => {
|
|
524
|
-
window.setTimeout(() => {
|
|
525
|
-
addToast({
|
|
526
|
-
message: `${variant.charAt(0).toUpperCase() + variant.slice(1)} toast message`,
|
|
527
|
-
variant,
|
|
528
|
-
duration: 6000,
|
|
529
|
-
});
|
|
530
|
-
}, index * 200);
|
|
531
|
-
});
|
|
532
|
-
}}
|
|
533
|
-
>
|
|
534
|
-
Show All Variants
|
|
535
|
-
</Button>
|
|
536
|
-
<Button
|
|
537
|
-
data-testid="glass-variants"
|
|
538
|
-
onClick={() => {
|
|
539
|
-
addToast({
|
|
540
|
-
message: 'Glass morphism effect with blur',
|
|
541
|
-
variant: 'success',
|
|
542
|
-
glass: true,
|
|
543
|
-
duration: 8000,
|
|
544
|
-
});
|
|
545
|
-
}}
|
|
546
|
-
>
|
|
547
|
-
Glass Effect
|
|
548
|
-
</Button>
|
|
549
|
-
</Stack>
|
|
550
|
-
);
|
|
551
|
-
},
|
|
552
|
-
play: async ({ canvasElement }) => {
|
|
553
|
-
const canvas = within(canvasElement);
|
|
554
|
-
const allVariantsButton = canvas.getByTestId('all-variants');
|
|
555
|
-
const glassButton = canvas.getByTestId('glass-variants');
|
|
556
|
-
|
|
557
|
-
// Test all variant states
|
|
558
|
-
await userEvent.click(allVariantsButton);
|
|
559
|
-
|
|
560
|
-
await waitFor(
|
|
561
|
-
() => {
|
|
562
|
-
const toastElements = document.querySelectorAll('[role="alert"]');
|
|
563
|
-
expect(toastElements.length).toBeGreaterThan(0);
|
|
564
|
-
},
|
|
565
|
-
{ timeout: 2000 },
|
|
566
|
-
);
|
|
567
|
-
|
|
568
|
-
// Test glass effect
|
|
569
|
-
await userEvent.click(glassButton);
|
|
570
|
-
|
|
571
|
-
await waitFor(() => {
|
|
572
|
-
const glassToast = document.querySelector('[role="alert"]');
|
|
573
|
-
if (glassToast) {
|
|
574
|
-
const computedStyle = window.getComputedStyle(glassToast);
|
|
575
|
-
expect(computedStyle.backdropFilter || computedStyle.webkitBackdropFilter).toBeTruthy();
|
|
576
|
-
}
|
|
577
|
-
});
|
|
578
|
-
},
|
|
579
|
-
};
|
|
580
|
-
|
|
581
|
-
// Performance Tests
|
|
582
|
-
export const Performance: Story = {
|
|
583
|
-
render: function PerformanceTest() {
|
|
584
|
-
const { addToast, clearAllToasts } = useToast();
|
|
585
|
-
const [isStressing, setIsStressing] = useState(false);
|
|
586
|
-
|
|
587
|
-
const stressTest = async () => {
|
|
588
|
-
setIsStressing(true);
|
|
589
|
-
const startTime = window.performance.now();
|
|
590
|
-
|
|
591
|
-
// Add many toasts rapidly
|
|
592
|
-
for (let i = 0; i < 50; i++) {
|
|
593
|
-
addToast({
|
|
594
|
-
message: `Performance test toast #${i + 1}`,
|
|
595
|
-
variant: i % 2 === 0 ? 'success' : 'info',
|
|
596
|
-
duration: 2000,
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
const endTime = window.performance.now();
|
|
601
|
-
const duration = endTime - startTime;
|
|
602
|
-
|
|
603
|
-
window.setTimeout(() => {
|
|
604
|
-
addToast({
|
|
605
|
-
message: `Stress test completed in ${duration.toFixed(2)}ms`,
|
|
606
|
-
variant: 'success',
|
|
607
|
-
persistent: true,
|
|
608
|
-
});
|
|
609
|
-
setIsStressing(false);
|
|
610
|
-
}, 1000);
|
|
611
|
-
};
|
|
612
|
-
|
|
613
|
-
return (
|
|
614
|
-
<Stack spacing={2} sx={{ minWidth: 300 }}>
|
|
615
|
-
<Typography variant="h6">Performance Test</Typography>
|
|
616
|
-
<Button data-testid="stress-test" onClick={stressTest} disabled={isStressing}>
|
|
617
|
-
{isStressing ? 'Running Stress Test...' : 'Run Stress Test (50 toasts)'}
|
|
618
|
-
</Button>
|
|
619
|
-
<Button data-testid="clear-performance" onClick={clearAllToasts}>
|
|
620
|
-
Clear All Toasts
|
|
621
|
-
</Button>
|
|
622
|
-
</Stack>
|
|
623
|
-
);
|
|
624
|
-
},
|
|
625
|
-
play: async ({ canvasElement }) => {
|
|
626
|
-
const canvas = within(canvasElement);
|
|
627
|
-
const stressButton = canvas.getByTestId('stress-test');
|
|
628
|
-
const clearButton = canvas.getByTestId('clear-performance');
|
|
629
|
-
|
|
630
|
-
const startTime = window.performance.now();
|
|
631
|
-
await userEvent.click(stressButton);
|
|
632
|
-
|
|
633
|
-
// Wait for stress test to complete
|
|
634
|
-
await waitFor(
|
|
635
|
-
() => {
|
|
636
|
-
const button = canvas.getByTestId('stress-test');
|
|
637
|
-
expect(button).not.toBeDisabled();
|
|
638
|
-
},
|
|
639
|
-
{ timeout: 10000 },
|
|
640
|
-
);
|
|
641
|
-
|
|
642
|
-
const endTime = window.performance.now();
|
|
643
|
-
const testDuration = endTime - startTime;
|
|
644
|
-
|
|
645
|
-
// Performance assertion - should complete within reasonable time
|
|
646
|
-
expect(testDuration).toBeLessThan(5000);
|
|
647
|
-
|
|
648
|
-
// Clean up
|
|
649
|
-
await userEvent.click(clearButton);
|
|
650
|
-
},
|
|
651
|
-
};
|
|
652
|
-
|
|
653
|
-
// Edge Cases Tests
|
|
654
|
-
export const EdgeCases: Story = {
|
|
655
|
-
render: function EdgeCasesTest() {
|
|
656
|
-
const { addToast, promise } = useToast();
|
|
657
|
-
|
|
658
|
-
const testLongMessage = () => {
|
|
659
|
-
addToast({
|
|
660
|
-
message:
|
|
661
|
-
'This is a very long toast message that should handle text wrapping and overflow gracefully. It contains multiple sentences and should demonstrate how the toast component handles extensive content without breaking the layout or becoming unusable.',
|
|
662
|
-
variant: 'info',
|
|
663
|
-
duration: 10000,
|
|
664
|
-
});
|
|
665
|
-
};
|
|
666
|
-
|
|
667
|
-
const testSpecialCharacters = () => {
|
|
668
|
-
addToast({
|
|
669
|
-
message:
|
|
670
|
-
'🚀 Special characters: áéíóú ñ ¡¿ @#$%^&*() "quotes" \'apostrophes\' <tags> & HTML entities',
|
|
671
|
-
variant: 'warning',
|
|
672
|
-
});
|
|
673
|
-
};
|
|
674
|
-
|
|
675
|
-
const testPromiseRace = async () => {
|
|
676
|
-
// Test multiple promises at once
|
|
677
|
-
const promises = [
|
|
678
|
-
new Promise((resolve) => window.setTimeout(() => resolve('First'), 1000)),
|
|
679
|
-
new Promise((resolve) => window.setTimeout(() => resolve('Second'), 1500)),
|
|
680
|
-
new Promise((_, reject) => window.setTimeout(() => reject('Third failed'), 2000)),
|
|
681
|
-
];
|
|
682
|
-
|
|
683
|
-
promises.forEach((p, i) => {
|
|
684
|
-
promise(p, {
|
|
685
|
-
loading: `Loading promise ${i + 1}...`,
|
|
686
|
-
success: (data) => `Promise ${i + 1} success: ${data}`,
|
|
687
|
-
error: (error) => `Promise ${i + 1} failed: ${error}`,
|
|
688
|
-
}).catch(() => {}); // Ignore rejections for test
|
|
689
|
-
});
|
|
690
|
-
};
|
|
691
|
-
|
|
692
|
-
return (
|
|
693
|
-
<Stack spacing={2} sx={{ minWidth: 300 }}>
|
|
694
|
-
<Typography variant="h6">Edge Cases Test</Typography>
|
|
695
|
-
<Button data-testid="long-message" onClick={testLongMessage}>
|
|
696
|
-
Long Message
|
|
697
|
-
</Button>
|
|
698
|
-
<Button data-testid="special-chars" onClick={testSpecialCharacters}>
|
|
699
|
-
Special Characters
|
|
700
|
-
</Button>
|
|
701
|
-
<Button data-testid="promise-race" onClick={testPromiseRace}>
|
|
702
|
-
Promise Race Condition
|
|
703
|
-
</Button>
|
|
704
|
-
<Button
|
|
705
|
-
data-testid="zero-duration"
|
|
706
|
-
onClick={() =>
|
|
707
|
-
addToast({
|
|
708
|
-
message: 'Zero duration toast (persistent)',
|
|
709
|
-
variant: 'success',
|
|
710
|
-
duration: 0,
|
|
711
|
-
})
|
|
712
|
-
}
|
|
713
|
-
>
|
|
714
|
-
Zero Duration
|
|
715
|
-
</Button>
|
|
716
|
-
</Stack>
|
|
717
|
-
);
|
|
718
|
-
},
|
|
719
|
-
play: async ({ canvasElement }) => {
|
|
720
|
-
const canvas = within(canvasElement);
|
|
721
|
-
|
|
722
|
-
// Test long message
|
|
723
|
-
const longMessageButton = canvas.getByTestId('long-message');
|
|
724
|
-
await userEvent.click(longMessageButton);
|
|
725
|
-
|
|
726
|
-
await waitFor(() => {
|
|
727
|
-
const toastElement = document.querySelector('[role="alert"]');
|
|
728
|
-
expect(toastElement).toBeInTheDocument();
|
|
729
|
-
expect(toastElement?.textContent?.length).toBeGreaterThan(100);
|
|
730
|
-
});
|
|
731
|
-
|
|
732
|
-
// Test special characters
|
|
733
|
-
const specialCharsButton = canvas.getByTestId('special-chars');
|
|
734
|
-
await userEvent.click(specialCharsButton);
|
|
735
|
-
|
|
736
|
-
await waitFor(() => {
|
|
737
|
-
const toastElements = document.querySelectorAll('[role="alert"]');
|
|
738
|
-
const specialCharToast = Array.from(toastElements).find((el) =>
|
|
739
|
-
el.textContent?.includes('🚀'),
|
|
740
|
-
);
|
|
741
|
-
expect(specialCharToast).toBeInTheDocument();
|
|
742
|
-
});
|
|
743
|
-
|
|
744
|
-
// Test zero duration (should be persistent)
|
|
745
|
-
const zeroDurationButton = canvas.getByTestId('zero-duration');
|
|
746
|
-
await userEvent.click(zeroDurationButton);
|
|
747
|
-
|
|
748
|
-
// Zero duration toasts should persist (not auto-dismiss)
|
|
749
|
-
await waitFor(
|
|
750
|
-
() => {
|
|
751
|
-
const toastElements = document.querySelectorAll('[role="alert"]');
|
|
752
|
-
const zeroDurationToast = Array.from(toastElements).find((el) =>
|
|
753
|
-
el.textContent?.includes('Zero duration'),
|
|
754
|
-
);
|
|
755
|
-
expect(zeroDurationToast).toBeInTheDocument();
|
|
756
|
-
},
|
|
757
|
-
{ timeout: 1000 },
|
|
758
|
-
);
|
|
759
|
-
},
|
|
760
|
-
};
|
|
761
|
-
|
|
762
|
-
// Integration Tests
|
|
763
|
-
export const Integration: Story = {
|
|
764
|
-
render: function IntegrationTest() {
|
|
765
|
-
const { addToast } = useToast();
|
|
766
|
-
|
|
767
|
-
return (
|
|
768
|
-
<Box sx={{ minWidth: 400 }}>
|
|
769
|
-
<Typography variant="h6" gutterBottom>
|
|
770
|
-
Integration Test
|
|
771
|
-
</Typography>
|
|
772
|
-
<Stack spacing={2}>
|
|
773
|
-
<Button
|
|
774
|
-
data-testid="integration-setup"
|
|
775
|
-
onClick={() => {
|
|
776
|
-
// Simulate a complete user workflow
|
|
777
|
-
addToast({ message: 'Step 1: Initializing...', variant: 'info' });
|
|
778
|
-
|
|
779
|
-
window.setTimeout(() => {
|
|
780
|
-
addToast({
|
|
781
|
-
message: 'Step 2: Processing data...',
|
|
782
|
-
variant: 'warning',
|
|
783
|
-
action: {
|
|
784
|
-
label: 'Cancel',
|
|
785
|
-
onClick: () => addToast({ message: 'Process cancelled', variant: 'error' }),
|
|
786
|
-
},
|
|
787
|
-
});
|
|
788
|
-
}, 1000);
|
|
789
|
-
|
|
790
|
-
window.setTimeout(() => {
|
|
791
|
-
addToast({
|
|
792
|
-
message: 'Step 3: Operation completed successfully!',
|
|
793
|
-
variant: 'success',
|
|
794
|
-
glass: true,
|
|
795
|
-
duration: 8000,
|
|
796
|
-
});
|
|
797
|
-
}, 2000);
|
|
798
|
-
}}
|
|
799
|
-
>
|
|
800
|
-
Run Integration Test
|
|
801
|
-
</Button>
|
|
802
|
-
</Stack>
|
|
803
|
-
</Box>
|
|
804
|
-
);
|
|
805
|
-
},
|
|
806
|
-
play: async ({ canvasElement }) => {
|
|
807
|
-
const canvas = within(canvasElement);
|
|
808
|
-
const integrationButton = canvas.getByTestId('integration-setup');
|
|
809
|
-
|
|
810
|
-
await userEvent.click(integrationButton);
|
|
811
|
-
|
|
812
|
-
// Wait for first toast
|
|
813
|
-
await waitFor(() => {
|
|
814
|
-
const toastElement = document.querySelector('[role="alert"]');
|
|
815
|
-
expect(toastElement).toBeInTheDocument();
|
|
816
|
-
expect(toastElement?.textContent).toContain('Step 1');
|
|
817
|
-
});
|
|
818
|
-
|
|
819
|
-
// Wait for workflow completion
|
|
820
|
-
await waitFor(
|
|
821
|
-
() => {
|
|
822
|
-
const successToast = Array.from(document.querySelectorAll('[role="alert"]')).find((el) =>
|
|
823
|
-
el.textContent?.includes('Step 3'),
|
|
824
|
-
);
|
|
825
|
-
expect(successToast).toBeInTheDocument();
|
|
826
|
-
},
|
|
827
|
-
{ timeout: 5000 },
|
|
828
|
-
);
|
|
829
|
-
|
|
830
|
-
// Verify ToastContainer is rendering toasts
|
|
831
|
-
const toastElements = document.querySelectorAll('[role="alert"]');
|
|
832
|
-
expect(toastElements.length).toBeGreaterThan(0);
|
|
833
|
-
},
|
|
834
|
-
};
|