@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,763 +0,0 @@
|
|
|
1
|
-
import { Button, createTheme,ThemeProvider } from '@mui/material';
|
|
2
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
|
-
import { useState } from 'react';
|
|
4
|
-
import { expect, fn,userEvent, waitFor, within } from 'storybook/test';
|
|
5
|
-
|
|
6
|
-
import { AlertDialog } from './AlertDialog';
|
|
7
|
-
import type { AlertDialogProps } from './AlertDialog.types';
|
|
8
|
-
|
|
9
|
-
const meta: Meta<typeof AlertDialog> = {
|
|
10
|
-
title: 'DataDisplay/AlertDialog/Tests',
|
|
11
|
-
component: AlertDialog,
|
|
12
|
-
parameters: {
|
|
13
|
-
layout: 'centered',
|
|
14
|
-
chromatic: { disableSnapshot: false },
|
|
15
|
-
},
|
|
16
|
-
tags: ['autodocs', 'test', 'component:AlertDialog'],
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export default meta;
|
|
20
|
-
type Story = StoryObj<typeof meta>;
|
|
21
|
-
|
|
22
|
-
// Helper component to manage dialog state
|
|
23
|
-
interface DialogWrapperProps extends Omit<AlertDialogProps, 'open' | 'onClose'> {
|
|
24
|
-
defaultOpen?: boolean;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const DialogWrapper = ({
|
|
28
|
-
onConfirm = fn(),
|
|
29
|
-
onCancel = fn(),
|
|
30
|
-
defaultOpen = false,
|
|
31
|
-
...props
|
|
32
|
-
}: DialogWrapperProps) => {
|
|
33
|
-
const [open, setOpen] = useState(defaultOpen);
|
|
34
|
-
|
|
35
|
-
const handleOpen = () => setOpen(true);
|
|
36
|
-
const handleClose = () => {
|
|
37
|
-
setOpen(false);
|
|
38
|
-
onCancel();
|
|
39
|
-
};
|
|
40
|
-
const handleConfirm = () => {
|
|
41
|
-
onConfirm();
|
|
42
|
-
setOpen(false);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<>
|
|
47
|
-
<Button onClick={handleOpen} data-testid="open-dialog">
|
|
48
|
-
Open Dialog
|
|
49
|
-
</Button>
|
|
50
|
-
<AlertDialog
|
|
51
|
-
open={open}
|
|
52
|
-
onClose={handleClose}
|
|
53
|
-
onCancel={handleClose}
|
|
54
|
-
onConfirm={handleConfirm}
|
|
55
|
-
{...(props as Partial<AlertDialogProps>)}
|
|
56
|
-
/>
|
|
57
|
-
</>
|
|
58
|
-
);
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
// Test 1: Basic Interaction
|
|
62
|
-
export const BasicInteraction: Story = {
|
|
63
|
-
render: () => {
|
|
64
|
-
const handleConfirm = fn();
|
|
65
|
-
const handleCancel = fn();
|
|
66
|
-
|
|
67
|
-
return (
|
|
68
|
-
<DialogWrapper
|
|
69
|
-
title="Confirm Action"
|
|
70
|
-
description="Are you sure you want to proceed?"
|
|
71
|
-
onConfirm={handleConfirm}
|
|
72
|
-
onCancel={handleCancel}
|
|
73
|
-
/>
|
|
74
|
-
);
|
|
75
|
-
},
|
|
76
|
-
play: async ({ canvasElement, step }) => {
|
|
77
|
-
const canvas = within(canvasElement);
|
|
78
|
-
|
|
79
|
-
await step('Open dialog', async () => {
|
|
80
|
-
const openButton = canvas.getByTestId('open-dialog');
|
|
81
|
-
await userEvent.click(openButton);
|
|
82
|
-
await waitFor(() => {
|
|
83
|
-
expect(within(document.body).getByText('Confirm Action')).toBeInTheDocument();
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
await step('Verify dialog content', async () => {
|
|
88
|
-
expect(
|
|
89
|
-
within(document.body).getByText('Are you sure you want to proceed?'),
|
|
90
|
-
).toBeInTheDocument();
|
|
91
|
-
expect(within(document.body).getByText('Cancel')).toBeInTheDocument();
|
|
92
|
-
expect(within(document.body).getByText('Confirm')).toBeInTheDocument();
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
await step('Click confirm button', async () => {
|
|
96
|
-
const confirmButton = within(document.body).getByText('Confirm');
|
|
97
|
-
await userEvent.click(confirmButton);
|
|
98
|
-
await waitFor(() => {
|
|
99
|
-
expect(within(document.body).queryByText('Confirm Action')).not.toBeInTheDocument();
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
await step('Open dialog again and click cancel', async () => {
|
|
104
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
105
|
-
await waitFor(() => {
|
|
106
|
-
expect(within(document.body).getByText('Confirm Action')).toBeInTheDocument();
|
|
107
|
-
});
|
|
108
|
-
const cancelButton = within(document.body).getByText('Cancel');
|
|
109
|
-
await userEvent.click(cancelButton);
|
|
110
|
-
await waitFor(() => {
|
|
111
|
-
expect(within(document.body).queryByText('Confirm Action')).not.toBeInTheDocument();
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
// Test 2: Form Interaction (with custom content)
|
|
118
|
-
const FormInteractionComponent = () => {
|
|
119
|
-
const [inputValue, setInputValue] = useState('');
|
|
120
|
-
const handleConfirm = fn();
|
|
121
|
-
|
|
122
|
-
return (
|
|
123
|
-
<DialogWrapper
|
|
124
|
-
title="Enter Details"
|
|
125
|
-
description="Please provide additional information"
|
|
126
|
-
onConfirm={handleConfirm}
|
|
127
|
-
confirmDisabled={inputValue.length === 0}
|
|
128
|
-
>
|
|
129
|
-
<input
|
|
130
|
-
type="text"
|
|
131
|
-
placeholder="Enter text"
|
|
132
|
-
value={inputValue}
|
|
133
|
-
onChange={(e) => setInputValue(e.target.value)}
|
|
134
|
-
data-testid="dialog-input"
|
|
135
|
-
style={{ marginTop: '10px', padding: '8px', width: '100%' }}
|
|
136
|
-
/>
|
|
137
|
-
</DialogWrapper>
|
|
138
|
-
);
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
export const FormInteraction: Story = {
|
|
142
|
-
render: () => <FormInteractionComponent />,
|
|
143
|
-
play: async ({ canvasElement, step }) => {
|
|
144
|
-
const canvas = within(canvasElement);
|
|
145
|
-
|
|
146
|
-
await step('Open dialog', async () => {
|
|
147
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
148
|
-
await waitFor(() => {
|
|
149
|
-
expect(within(document.body).getByText('Enter Details')).toBeInTheDocument();
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
await step('Verify confirm button is disabled initially', async () => {
|
|
154
|
-
const confirmButton = within(document.body).getByText('Confirm');
|
|
155
|
-
expect(confirmButton).toBeDisabled();
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
await step('Type in input field', async () => {
|
|
159
|
-
const input = within(document.body).getByTestId('dialog-input');
|
|
160
|
-
await userEvent.type(input, 'Test input');
|
|
161
|
-
await waitFor(() => {
|
|
162
|
-
expect(input).toHaveValue('Test input');
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
await step('Verify confirm button is enabled', async () => {
|
|
167
|
-
const confirmButton = within(document.body).getByText('Confirm');
|
|
168
|
-
expect(confirmButton).toBeEnabled();
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
await step('Submit form', async () => {
|
|
172
|
-
const confirmButton = within(document.body).getByText('Confirm');
|
|
173
|
-
await userEvent.click(confirmButton);
|
|
174
|
-
await waitFor(() => {
|
|
175
|
-
expect(within(document.body).queryByText('Enter Details')).not.toBeInTheDocument();
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
},
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
// Test 3: Keyboard Navigation
|
|
182
|
-
export const KeyboardNavigation: Story = {
|
|
183
|
-
render: () => (
|
|
184
|
-
<DialogWrapper
|
|
185
|
-
defaultOpen={true}
|
|
186
|
-
title="Keyboard Test"
|
|
187
|
-
description="Test keyboard navigation"
|
|
188
|
-
/>
|
|
189
|
-
),
|
|
190
|
-
play: async ({ canvasElement, step }) => {
|
|
191
|
-
const canvas = within(canvasElement);
|
|
192
|
-
|
|
193
|
-
await step('Verify dialog is open', async () => {
|
|
194
|
-
await waitFor(() => {
|
|
195
|
-
expect(within(document.body).getByText('Keyboard Test')).toBeInTheDocument();
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
await step('Press Escape to close dialog', async () => {
|
|
200
|
-
await userEvent.keyboard('{Escape}');
|
|
201
|
-
await waitFor(() => {
|
|
202
|
-
expect(within(document.body).queryByText('Keyboard Test')).not.toBeInTheDocument();
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
await step('Open dialog and navigate with Tab', async () => {
|
|
207
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
208
|
-
await waitFor(() => {
|
|
209
|
-
expect(within(document.body).getByText('Keyboard Test')).toBeInTheDocument();
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// Tab navigation - the Confirm button should have autoFocus
|
|
213
|
-
await waitFor(() => {
|
|
214
|
-
const confirmButton = within(document.body).getByText('Confirm');
|
|
215
|
-
expect(document.activeElement).toBe(confirmButton);
|
|
216
|
-
});
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
await step('Press Enter on focused button', async () => {
|
|
220
|
-
await userEvent.keyboard('{Enter}');
|
|
221
|
-
await waitFor(() => {
|
|
222
|
-
expect(within(document.body).queryByText('Keyboard Test')).not.toBeInTheDocument();
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
},
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
// Test 4: Screen Reader
|
|
229
|
-
export const ScreenReader: Story = {
|
|
230
|
-
render: () => (
|
|
231
|
-
<DialogWrapper
|
|
232
|
-
title="Accessible Dialog"
|
|
233
|
-
description="This dialog has proper ARIA attributes"
|
|
234
|
-
variant="default"
|
|
235
|
-
/>
|
|
236
|
-
),
|
|
237
|
-
play: async ({ canvasElement, step }) => {
|
|
238
|
-
const canvas = within(canvasElement);
|
|
239
|
-
|
|
240
|
-
await step('Open dialog', async () => {
|
|
241
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
242
|
-
await waitFor(() => {
|
|
243
|
-
expect(within(document.body).getByText('Accessible Dialog')).toBeInTheDocument();
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
await step('Verify ARIA attributes', async () => {
|
|
248
|
-
const dialog = within(document.body).getByRole('dialog');
|
|
249
|
-
expect(dialog).toBeInTheDocument();
|
|
250
|
-
|
|
251
|
-
const closeButton = within(document.body).getByLabelText('close');
|
|
252
|
-
expect(closeButton).toBeInTheDocument();
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
await step('Verify dialog title and description', async () => {
|
|
256
|
-
expect(within(document.body).getByText('Accessible Dialog')).toBeInTheDocument();
|
|
257
|
-
expect(
|
|
258
|
-
within(document.body).getByText('This dialog has proper ARIA attributes'),
|
|
259
|
-
).toBeInTheDocument();
|
|
260
|
-
});
|
|
261
|
-
},
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
// Test 5: Focus Management
|
|
265
|
-
export const FocusManagement: Story = {
|
|
266
|
-
render: () => (
|
|
267
|
-
<DialogWrapper
|
|
268
|
-
defaultOpen={true}
|
|
269
|
-
title="Focus Test"
|
|
270
|
-
description="Testing focus trap and management"
|
|
271
|
-
/>
|
|
272
|
-
),
|
|
273
|
-
play: async ({ step }) => {
|
|
274
|
-
await step('Verify dialog is open', async () => {
|
|
275
|
-
await waitFor(() => {
|
|
276
|
-
expect(within(document.body).getByText('Focus Test')).toBeInTheDocument();
|
|
277
|
-
});
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
await step('Verify focus is trapped in dialog', async () => {
|
|
281
|
-
// Initial focus should be on confirm button (autoFocus)
|
|
282
|
-
await waitFor(() => {
|
|
283
|
-
const confirmButton = within(document.body).getByText('Confirm');
|
|
284
|
-
expect(document.activeElement).toBe(confirmButton);
|
|
285
|
-
});
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
await step('Tab through focusable elements', async () => {
|
|
289
|
-
// Tab cycles through dialog elements
|
|
290
|
-
await userEvent.tab();
|
|
291
|
-
await waitFor(() =>
|
|
292
|
-
expect(document.activeElement?.getAttribute('aria-label')).toBe('close'),
|
|
293
|
-
);
|
|
294
|
-
|
|
295
|
-
await userEvent.tab();
|
|
296
|
-
await waitFor(() => expect(document.activeElement?.textContent).toContain('Cancel'));
|
|
297
|
-
|
|
298
|
-
await userEvent.tab();
|
|
299
|
-
await waitFor(() => expect(document.activeElement?.textContent).toContain('Confirm'));
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
await step('Close dialog and verify focus return', async () => {
|
|
303
|
-
await userEvent.keyboard('{Escape}');
|
|
304
|
-
await waitFor(() => {
|
|
305
|
-
expect(within(document.body).queryByText('Focus Test')).not.toBeInTheDocument();
|
|
306
|
-
});
|
|
307
|
-
});
|
|
308
|
-
},
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
// Test 6: Responsive Design
|
|
312
|
-
export const ResponsiveDesign: Story = {
|
|
313
|
-
render: () => (
|
|
314
|
-
<DialogWrapper
|
|
315
|
-
title="Responsive Dialog"
|
|
316
|
-
description="This dialog adapts to different screen sizes. Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
|
317
|
-
variant="default"
|
|
318
|
-
/>
|
|
319
|
-
),
|
|
320
|
-
parameters: {
|
|
321
|
-
viewport: {
|
|
322
|
-
viewports: {
|
|
323
|
-
mobile: { name: 'Mobile', styles: { width: '360px', height: '640px' } },
|
|
324
|
-
tablet: { name: 'Tablet', styles: { width: '768px', height: '1024px' } },
|
|
325
|
-
desktop: { name: 'Desktop', styles: { width: '1920px', height: '1080px' } },
|
|
326
|
-
},
|
|
327
|
-
},
|
|
328
|
-
},
|
|
329
|
-
play: async ({ canvasElement, step }) => {
|
|
330
|
-
const canvas = within(canvasElement);
|
|
331
|
-
|
|
332
|
-
await step('Open dialog on mobile viewport', async () => {
|
|
333
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
334
|
-
await waitFor(() => {
|
|
335
|
-
expect(within(document.body).getByText('Responsive Dialog')).toBeInTheDocument();
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
await step('Verify dialog is visible and properly sized', async () => {
|
|
340
|
-
const dialog = within(document.body).getByRole('dialog');
|
|
341
|
-
expect(dialog).toBeInTheDocument();
|
|
342
|
-
expect(within(document.body).getByText(/Lorem ipsum/)).toBeInTheDocument();
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
await step('Close dialog', async () => {
|
|
346
|
-
const closeButton = within(document.body).getByLabelText('close');
|
|
347
|
-
await userEvent.click(closeButton);
|
|
348
|
-
await waitFor(() => {
|
|
349
|
-
expect(within(document.body).queryByText('Responsive Dialog')).not.toBeInTheDocument();
|
|
350
|
-
});
|
|
351
|
-
});
|
|
352
|
-
},
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
// Test 7: Theme Variations
|
|
356
|
-
const ThemeVariationsComponent = () => {
|
|
357
|
-
const [theme, setTheme] = useState<'light' | 'dark'>('light');
|
|
358
|
-
|
|
359
|
-
const muiTheme = createTheme({
|
|
360
|
-
palette: {
|
|
361
|
-
mode: theme,
|
|
362
|
-
},
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
return (
|
|
366
|
-
<ThemeProvider theme={muiTheme}>
|
|
367
|
-
<div style={{ padding: '20px', backgroundColor: theme === 'dark' ? '#121212' : '#fff' }}>
|
|
368
|
-
<Button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>Toggle Theme</Button>
|
|
369
|
-
<DialogWrapper
|
|
370
|
-
title="Theme Test"
|
|
371
|
-
description="Testing in different themes"
|
|
372
|
-
variant="default"
|
|
373
|
-
/>
|
|
374
|
-
</div>
|
|
375
|
-
</ThemeProvider>
|
|
376
|
-
);
|
|
377
|
-
};
|
|
378
|
-
|
|
379
|
-
export const ThemeVariations: Story = {
|
|
380
|
-
render: () => <ThemeVariationsComponent />,
|
|
381
|
-
play: async ({ canvasElement, step }) => {
|
|
382
|
-
const canvas = within(canvasElement);
|
|
383
|
-
|
|
384
|
-
await step('Open dialog in light theme', async () => {
|
|
385
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
386
|
-
await waitFor(() => {
|
|
387
|
-
expect(within(document.body).getByText('Theme Test')).toBeInTheDocument();
|
|
388
|
-
});
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
await step('Close dialog', async () => {
|
|
392
|
-
await userEvent.keyboard('{Escape}');
|
|
393
|
-
await waitFor(() => {
|
|
394
|
-
expect(within(document.body).queryByText('Theme Test')).not.toBeInTheDocument();
|
|
395
|
-
});
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
await step('Switch to dark theme', async () => {
|
|
399
|
-
const themeToggle = within(document.body).getByText('Toggle Theme');
|
|
400
|
-
await userEvent.click(themeToggle);
|
|
401
|
-
await waitFor(() => {
|
|
402
|
-
expect(
|
|
403
|
-
canvasElement.querySelector('[style*="background-color: rgb(18, 18, 18)"]'),
|
|
404
|
-
).toBeInTheDocument();
|
|
405
|
-
});
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
await step('Open dialog in dark theme', async () => {
|
|
409
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
410
|
-
await waitFor(() => {
|
|
411
|
-
expect(within(document.body).getByText('Theme Test')).toBeInTheDocument();
|
|
412
|
-
});
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
await step('Verify dialog renders correctly in dark theme', async () => {
|
|
416
|
-
const dialog = within(document.body).getByRole('dialog');
|
|
417
|
-
expect(dialog).toBeInTheDocument();
|
|
418
|
-
});
|
|
419
|
-
},
|
|
420
|
-
};
|
|
421
|
-
|
|
422
|
-
// Test 8: Visual States
|
|
423
|
-
const VisualStatesComponent = () => {
|
|
424
|
-
const [variant, setVariant] = useState<'default' | 'destructive' | 'glass'>('default');
|
|
425
|
-
const [glow, setGlow] = useState(false);
|
|
426
|
-
const [pulse, setPulse] = useState(false);
|
|
427
|
-
const [loading, setLoading] = useState(false);
|
|
428
|
-
|
|
429
|
-
return (
|
|
430
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
|
|
431
|
-
<div style={{ display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
|
|
432
|
-
<Button onClick={() => setVariant('default')}>Default</Button>
|
|
433
|
-
<Button onClick={() => setVariant('destructive')}>Destructive</Button>
|
|
434
|
-
<Button onClick={() => setVariant('glass')}>Glass</Button>
|
|
435
|
-
<Button onClick={() => setGlow(!glow)}>Toggle Glow</Button>
|
|
436
|
-
<Button onClick={() => setPulse(!pulse)}>Toggle Pulse</Button>
|
|
437
|
-
<Button onClick={() => setLoading(!loading)}>Toggle Loading</Button>
|
|
438
|
-
</div>
|
|
439
|
-
<DialogWrapper
|
|
440
|
-
title={`${variant} Variant`}
|
|
441
|
-
description={`This is a ${variant} dialog with glow: ${glow}, pulse: ${pulse}`}
|
|
442
|
-
variant={variant}
|
|
443
|
-
glow={glow}
|
|
444
|
-
pulse={pulse}
|
|
445
|
-
loading={loading}
|
|
446
|
-
/>
|
|
447
|
-
</div>
|
|
448
|
-
);
|
|
449
|
-
};
|
|
450
|
-
|
|
451
|
-
export const VisualStates: Story = {
|
|
452
|
-
render: () => <VisualStatesComponent />,
|
|
453
|
-
play: async ({ canvasElement, step }) => {
|
|
454
|
-
const canvas = within(canvasElement);
|
|
455
|
-
|
|
456
|
-
await step('Test default variant', async () => {
|
|
457
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
458
|
-
await waitFor(() => {
|
|
459
|
-
expect(within(document.body).getByText('default Variant')).toBeInTheDocument();
|
|
460
|
-
});
|
|
461
|
-
await userEvent.keyboard('{Escape}');
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
await step('Test destructive variant', async () => {
|
|
465
|
-
await userEvent.click(within(document.body).getByText('Destructive'));
|
|
466
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
467
|
-
await waitFor(() => {
|
|
468
|
-
expect(within(document.body).getByText('destructive Variant')).toBeInTheDocument();
|
|
469
|
-
});
|
|
470
|
-
await userEvent.keyboard('{Escape}');
|
|
471
|
-
});
|
|
472
|
-
|
|
473
|
-
await step('Test glass variant', async () => {
|
|
474
|
-
await userEvent.click(within(document.body).getByText('Glass'));
|
|
475
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
476
|
-
await waitFor(() => {
|
|
477
|
-
expect(within(document.body).getByText('glass Variant')).toBeInTheDocument();
|
|
478
|
-
});
|
|
479
|
-
await userEvent.keyboard('{Escape}');
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
await step('Test with glow effect', async () => {
|
|
483
|
-
await userEvent.click(within(document.body).getByText('Toggle Glow'));
|
|
484
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
485
|
-
await waitFor(() => {
|
|
486
|
-
expect(within(document.body).getByText(/glow: true/)).toBeInTheDocument();
|
|
487
|
-
});
|
|
488
|
-
await userEvent.keyboard('{Escape}');
|
|
489
|
-
});
|
|
490
|
-
|
|
491
|
-
await step('Test with pulse animation', async () => {
|
|
492
|
-
await userEvent.click(within(document.body).getByText('Toggle Pulse'));
|
|
493
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
494
|
-
await waitFor(() => {
|
|
495
|
-
expect(within(document.body).getByText(/pulse: true/)).toBeInTheDocument();
|
|
496
|
-
});
|
|
497
|
-
await userEvent.keyboard('{Escape}');
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
await step('Test loading state', async () => {
|
|
501
|
-
await userEvent.click(within(document.body).getByText('Toggle Loading'));
|
|
502
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
503
|
-
await waitFor(() => {
|
|
504
|
-
const confirmButton = within(document.body).getByText('Confirm');
|
|
505
|
-
expect(confirmButton).toBeInTheDocument();
|
|
506
|
-
// Check for loading indicator
|
|
507
|
-
const loadingIndicator = confirmButton.querySelector('[role="progressbar"]');
|
|
508
|
-
expect(loadingIndicator).toBeInTheDocument();
|
|
509
|
-
});
|
|
510
|
-
});
|
|
511
|
-
},
|
|
512
|
-
};
|
|
513
|
-
|
|
514
|
-
// Test 9: Performance
|
|
515
|
-
const PerformanceComponent = () => {
|
|
516
|
-
const [dialogCount, setDialogCount] = useState(0);
|
|
517
|
-
const [currentDialog, setCurrentDialog] = useState(0);
|
|
518
|
-
const [renderTime, setRenderTime] = useState<number | null>(null);
|
|
519
|
-
|
|
520
|
-
const handleOpen = () => {
|
|
521
|
-
const startTime = window.performance.now();
|
|
522
|
-
setDialogCount((prev) => prev + 1);
|
|
523
|
-
setCurrentDialog(dialogCount + 1);
|
|
524
|
-
// This is the demo measuring itself for display, not an assertion — the
|
|
525
|
-
// story renders the number rather than asserting on it, so nothing here
|
|
526
|
-
// can fail on a slow machine.
|
|
527
|
-
// eslint-disable-next-line test-flakiness/no-animation-wait -- demo self-measurement, not an assertion
|
|
528
|
-
window.requestAnimationFrame(() => {
|
|
529
|
-
const endTime = window.performance.now();
|
|
530
|
-
setRenderTime(endTime - startTime);
|
|
531
|
-
});
|
|
532
|
-
};
|
|
533
|
-
|
|
534
|
-
const handleClose = () => {
|
|
535
|
-
setCurrentDialog(0);
|
|
536
|
-
};
|
|
537
|
-
|
|
538
|
-
return (
|
|
539
|
-
<div>
|
|
540
|
-
<div style={{ marginBottom: '10px' }}>
|
|
541
|
-
<div>Dialogs opened: {dialogCount}</div>
|
|
542
|
-
{renderTime && <div>Last render time: {renderTime.toFixed(2)}ms</div>}
|
|
543
|
-
</div>
|
|
544
|
-
<Button onClick={handleOpen} data-testid="perf-open">
|
|
545
|
-
Open Dialog
|
|
546
|
-
</Button>
|
|
547
|
-
<AlertDialog
|
|
548
|
-
open={currentDialog > 0}
|
|
549
|
-
onClose={handleClose}
|
|
550
|
-
title={`Dialog ${currentDialog}`}
|
|
551
|
-
description="Performance test dialog"
|
|
552
|
-
/>
|
|
553
|
-
</div>
|
|
554
|
-
);
|
|
555
|
-
};
|
|
556
|
-
|
|
557
|
-
export const Performance: Story = {
|
|
558
|
-
render: () => <PerformanceComponent />,
|
|
559
|
-
play: async ({ canvasElement, step }) => {
|
|
560
|
-
const canvas = within(canvasElement);
|
|
561
|
-
|
|
562
|
-
await step('Open multiple dialogs and measure performance', async () => {
|
|
563
|
-
const openButton = canvas.getByTestId('perf-open');
|
|
564
|
-
|
|
565
|
-
// Open dialog 5 times
|
|
566
|
-
for (let i = 0; i < 5; i++) {
|
|
567
|
-
await userEvent.click(openButton);
|
|
568
|
-
await waitFor(() => {
|
|
569
|
-
expect(within(document.body).getByText(`Dialog ${i + 1}`)).toBeInTheDocument();
|
|
570
|
-
});
|
|
571
|
-
await userEvent.keyboard('{Escape}');
|
|
572
|
-
await waitFor(() => {
|
|
573
|
-
expect(within(document.body).queryByText(`Dialog ${i + 1}`)).not.toBeInTheDocument();
|
|
574
|
-
});
|
|
575
|
-
}
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
await step('Verify performance metrics displayed', async () => {
|
|
579
|
-
expect(canvas.getByText(/Dialogs opened: 5/)).toBeInTheDocument();
|
|
580
|
-
expect(canvas.getByText(/Last render time:/)).toBeInTheDocument();
|
|
581
|
-
});
|
|
582
|
-
},
|
|
583
|
-
};
|
|
584
|
-
|
|
585
|
-
// Test 10: Edge Cases
|
|
586
|
-
const EdgeCasesComponent = () => {
|
|
587
|
-
const [testCase, setTestCase] = useState<'long' | 'empty' | 'special' | 'noCancel'>('long');
|
|
588
|
-
|
|
589
|
-
const longText = 'Lorem ipsum dolor sit amet, '.repeat(50);
|
|
590
|
-
const specialChars = '!@#$%^&*()_+-=[]{}|;\':",./<>?`~\\';
|
|
591
|
-
|
|
592
|
-
return (
|
|
593
|
-
<div>
|
|
594
|
-
<div style={{ display: 'flex', gap: '10px', marginBottom: '10px', flexWrap: 'wrap' }}>
|
|
595
|
-
<Button onClick={() => setTestCase('long')}>Long Text</Button>
|
|
596
|
-
<Button onClick={() => setTestCase('empty')}>Empty Content</Button>
|
|
597
|
-
<Button onClick={() => setTestCase('special')}>Special Chars</Button>
|
|
598
|
-
<Button onClick={() => setTestCase('noCancel')}>No Cancel</Button>
|
|
599
|
-
</div>
|
|
600
|
-
<DialogWrapper
|
|
601
|
-
title={
|
|
602
|
-
testCase === 'empty'
|
|
603
|
-
? ''
|
|
604
|
-
: testCase === 'special'
|
|
605
|
-
? specialChars
|
|
606
|
-
: testCase === 'long'
|
|
607
|
-
? 'Very Long Title That Might Overflow The Dialog Header Area'
|
|
608
|
-
: 'No Cancel Button'
|
|
609
|
-
}
|
|
610
|
-
description={
|
|
611
|
-
testCase === 'empty'
|
|
612
|
-
? ''
|
|
613
|
-
: testCase === 'special'
|
|
614
|
-
? specialChars
|
|
615
|
-
: testCase === 'long'
|
|
616
|
-
? longText
|
|
617
|
-
: 'This dialog has no cancel button'
|
|
618
|
-
}
|
|
619
|
-
showCancel={testCase !== 'noCancel'}
|
|
620
|
-
/>
|
|
621
|
-
</div>
|
|
622
|
-
);
|
|
623
|
-
};
|
|
624
|
-
|
|
625
|
-
export const EdgeCases: Story = {
|
|
626
|
-
render: () => <EdgeCasesComponent />,
|
|
627
|
-
play: async ({ canvasElement, step }) => {
|
|
628
|
-
const canvas = within(canvasElement);
|
|
629
|
-
|
|
630
|
-
await step('Test long text overflow', async () => {
|
|
631
|
-
await userEvent.click(canvas.getByText('Long Text'));
|
|
632
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
633
|
-
await waitFor(() => {
|
|
634
|
-
expect(within(document.body).getByText(/Very Long Title/)).toBeInTheDocument();
|
|
635
|
-
});
|
|
636
|
-
await userEvent.keyboard('{Escape}');
|
|
637
|
-
});
|
|
638
|
-
|
|
639
|
-
await step('Test empty content', async () => {
|
|
640
|
-
await userEvent.click(canvas.getByText('Empty Content'));
|
|
641
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
642
|
-
await waitFor(() => {
|
|
643
|
-
// Dialog should still render with buttons
|
|
644
|
-
expect(within(document.body).getByText('Cancel')).toBeInTheDocument();
|
|
645
|
-
expect(within(document.body).getByText('Confirm')).toBeInTheDocument();
|
|
646
|
-
});
|
|
647
|
-
await userEvent.keyboard('{Escape}');
|
|
648
|
-
});
|
|
649
|
-
|
|
650
|
-
await step('Test special characters', async () => {
|
|
651
|
-
await userEvent.click(canvas.getByText('Special Chars'));
|
|
652
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
653
|
-
await waitFor(() => {
|
|
654
|
-
const specialTextElements = within(document.body).getAllByText(/!@#/);
|
|
655
|
-
expect(specialTextElements.length).toBeGreaterThan(0);
|
|
656
|
-
});
|
|
657
|
-
await userEvent.keyboard('{Escape}');
|
|
658
|
-
});
|
|
659
|
-
|
|
660
|
-
await step('Test no cancel button', async () => {
|
|
661
|
-
await userEvent.click(canvas.getByText('No Cancel'));
|
|
662
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
663
|
-
await waitFor(() => {
|
|
664
|
-
expect(within(document.body).getByText('No Cancel Button')).toBeInTheDocument();
|
|
665
|
-
expect(within(document.body).queryByText('Cancel')).not.toBeInTheDocument();
|
|
666
|
-
expect(within(document.body).getByText('Confirm')).toBeInTheDocument();
|
|
667
|
-
});
|
|
668
|
-
});
|
|
669
|
-
},
|
|
670
|
-
};
|
|
671
|
-
|
|
672
|
-
// Test 11: Integration
|
|
673
|
-
const IntegrationComponent = () => {
|
|
674
|
-
const [confirmations, setConfirmations] = useState<string[]>([]);
|
|
675
|
-
const [isDeleting, setIsDeleting] = useState(false);
|
|
676
|
-
|
|
677
|
-
const handleDelete = async () => {
|
|
678
|
-
setIsDeleting(true);
|
|
679
|
-
// The delay is the point of this story — it shows the pending state — so it
|
|
680
|
-
// is the demo's own behaviour rather than a test waiting for something.
|
|
681
|
-
// eslint-disable-next-line test-flakiness/no-hard-coded-timeout -- simulated latency is what this story demonstrates
|
|
682
|
-
await new Promise((resolve) => window.setTimeout(resolve, 1000));
|
|
683
|
-
// Numbered rather than timestamped: the entry only needs to be distinct, and
|
|
684
|
-
// a clock reading makes the rendered text different on every run.
|
|
685
|
-
setConfirmations((prev) => [...prev, `Deleted item ${prev.length + 1}`]);
|
|
686
|
-
setIsDeleting(false);
|
|
687
|
-
};
|
|
688
|
-
|
|
689
|
-
return (
|
|
690
|
-
<div>
|
|
691
|
-
<div style={{ marginBottom: '20px' }}>
|
|
692
|
-
<h3>Confirmation Log:</h3>
|
|
693
|
-
{confirmations.length === 0 ? (
|
|
694
|
-
<p>No actions confirmed yet</p>
|
|
695
|
-
) : (
|
|
696
|
-
<ul>
|
|
697
|
-
{confirmations.map((conf, index) => (
|
|
698
|
-
<li key={index}>{conf}</li>
|
|
699
|
-
))}
|
|
700
|
-
</ul>
|
|
701
|
-
)}
|
|
702
|
-
</div>
|
|
703
|
-
<DialogWrapper
|
|
704
|
-
variant="destructive"
|
|
705
|
-
title="Delete Item"
|
|
706
|
-
description="This action cannot be undone. Are you sure you want to delete this item?"
|
|
707
|
-
confirmText="Delete"
|
|
708
|
-
loading={isDeleting}
|
|
709
|
-
onConfirm={handleDelete}
|
|
710
|
-
/>
|
|
711
|
-
</div>
|
|
712
|
-
);
|
|
713
|
-
};
|
|
714
|
-
|
|
715
|
-
export const Integration: Story = {
|
|
716
|
-
render: () => <IntegrationComponent />,
|
|
717
|
-
play: async ({ canvasElement, step }) => {
|
|
718
|
-
const canvas = within(canvasElement);
|
|
719
|
-
|
|
720
|
-
await step('Verify initial state', async () => {
|
|
721
|
-
expect(canvas.getByText('No actions confirmed yet')).toBeInTheDocument();
|
|
722
|
-
});
|
|
723
|
-
|
|
724
|
-
await step('Open destructive dialog', async () => {
|
|
725
|
-
await userEvent.click(canvas.getByTestId('open-dialog'));
|
|
726
|
-
await waitFor(() => {
|
|
727
|
-
expect(within(document.body).getByText('Delete Item')).toBeInTheDocument();
|
|
728
|
-
});
|
|
729
|
-
});
|
|
730
|
-
|
|
731
|
-
await step('Verify destructive variant styling', async () => {
|
|
732
|
-
const deleteButton = within(document.body).getByText('Delete');
|
|
733
|
-
expect(deleteButton).toBeInTheDocument();
|
|
734
|
-
// Should have error color for destructive variant
|
|
735
|
-
expect(deleteButton).toHaveStyle({ backgroundColor: expect.stringContaining('rgb') });
|
|
736
|
-
});
|
|
737
|
-
|
|
738
|
-
await step('Confirm deletion', async () => {
|
|
739
|
-
const deleteButton = within(document.body).getByText('Delete');
|
|
740
|
-
await userEvent.click(deleteButton);
|
|
741
|
-
|
|
742
|
-
// Wait for loading state
|
|
743
|
-
await waitFor(() => {
|
|
744
|
-
const progressBar = document.body.querySelector('[role="progressbar"]');
|
|
745
|
-
expect(progressBar).toBeInTheDocument();
|
|
746
|
-
});
|
|
747
|
-
|
|
748
|
-
// Wait for completion
|
|
749
|
-
await waitFor(
|
|
750
|
-
() => {
|
|
751
|
-
expect(within(document.body).queryByText('Delete Item')).not.toBeInTheDocument();
|
|
752
|
-
},
|
|
753
|
-
{ timeout: 2000 },
|
|
754
|
-
);
|
|
755
|
-
});
|
|
756
|
-
|
|
757
|
-
await step('Verify action was logged', async () => {
|
|
758
|
-
await waitFor(() => {
|
|
759
|
-
expect(canvas.getByText(/Deleted item/)).toBeInTheDocument();
|
|
760
|
-
});
|
|
761
|
-
});
|
|
762
|
-
},
|
|
763
|
-
};
|