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