@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,1154 +0,0 @@
|
|
|
1
|
-
import Delete from '@mui/icons-material/Delete';
|
|
2
|
-
import Help from '@mui/icons-material/Help';
|
|
3
|
-
import Info from '@mui/icons-material/Info';
|
|
4
|
-
import { Box, Button, IconButton, Stack, Typography } from '@mui/material';
|
|
5
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
6
|
-
import React from 'react';
|
|
7
|
-
import { expect, userEvent, waitFor,within } from 'storybook/test';
|
|
8
|
-
|
|
9
|
-
import { Tooltip } from './Tooltip';
|
|
10
|
-
|
|
11
|
-
const meta: Meta<typeof Tooltip> = {
|
|
12
|
-
title: 'DataDisplay/Tooltip/Tests',
|
|
13
|
-
component: Tooltip,
|
|
14
|
-
parameters: {
|
|
15
|
-
layout: 'centered',
|
|
16
|
-
chromatic: { disableSnapshot: false },
|
|
17
|
-
},
|
|
18
|
-
tags: ['autodocs', 'test', 'component:Tooltip'],
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export default meta;
|
|
22
|
-
type Story = StoryObj<typeof meta>;
|
|
23
|
-
|
|
24
|
-
// Helper function to find tooltip by content or just the first visible one
|
|
25
|
-
const findTooltipByContent = async (content?: string) => {
|
|
26
|
-
const tooltips = await within(document.body).findAllByRole('tooltip');
|
|
27
|
-
if (!content) {
|
|
28
|
-
// Return the last tooltip (innermost div with actual content)
|
|
29
|
-
return tooltips[tooltips.length - 1];
|
|
30
|
-
}
|
|
31
|
-
return tooltips.find((tip) => tip.textContent?.includes(content));
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// 7.2 Interaction Tests
|
|
35
|
-
export const BasicInteraction: Story = {
|
|
36
|
-
name: '🧪 Basic Interaction Test',
|
|
37
|
-
args: {
|
|
38
|
-
title: 'Test tooltip content',
|
|
39
|
-
variant: 'default',
|
|
40
|
-
},
|
|
41
|
-
render: (args) => (
|
|
42
|
-
<Box sx={{ p: 4, display: 'flex', justifyContent: 'center' }}>
|
|
43
|
-
<Tooltip {...args}>
|
|
44
|
-
<Button variant="outlined" data-testid="trigger-button">
|
|
45
|
-
Hover me
|
|
46
|
-
</Button>
|
|
47
|
-
</Tooltip>
|
|
48
|
-
</Box>
|
|
49
|
-
),
|
|
50
|
-
play: async ({ canvasElement, step }) => {
|
|
51
|
-
const canvas = within(canvasElement);
|
|
52
|
-
|
|
53
|
-
await step('Initial render verification', async () => {
|
|
54
|
-
const button = canvas.getByTestId('trigger-button');
|
|
55
|
-
await expect(button).toBeInTheDocument();
|
|
56
|
-
await expect(button).toHaveTextContent('Hover me');
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
await step('Hover interaction shows tooltip', async () => {
|
|
60
|
-
const button = canvas.getByTestId('trigger-button');
|
|
61
|
-
await userEvent.hover(button);
|
|
62
|
-
|
|
63
|
-
// Wait for tooltip to appear
|
|
64
|
-
await waitFor(
|
|
65
|
-
async () => {
|
|
66
|
-
const tooltip = await findTooltipByContent('Test tooltip content');
|
|
67
|
-
await expect(tooltip).toBeInTheDocument();
|
|
68
|
-
await expect(tooltip).toHaveTextContent('Test tooltip content');
|
|
69
|
-
},
|
|
70
|
-
{ timeout: 2000 },
|
|
71
|
-
);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
await step('Unhover hides tooltip', async () => {
|
|
75
|
-
const button = canvas.getByTestId('trigger-button');
|
|
76
|
-
await userEvent.unhover(button);
|
|
77
|
-
|
|
78
|
-
// Wait for tooltip to disappear
|
|
79
|
-
await waitFor(
|
|
80
|
-
() => {
|
|
81
|
-
const tooltip = within(document.body).queryByRole('tooltip');
|
|
82
|
-
expect(tooltip).not.toBeInTheDocument();
|
|
83
|
-
},
|
|
84
|
-
{ timeout: 2000 },
|
|
85
|
-
);
|
|
86
|
-
});
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
export const ClickInteraction: Story = {
|
|
91
|
-
name: '🖱️ Click Interaction Test',
|
|
92
|
-
args: {
|
|
93
|
-
title: 'Click tooltip',
|
|
94
|
-
variant: 'light',
|
|
95
|
-
},
|
|
96
|
-
render: (args) => (
|
|
97
|
-
<Box sx={{ p: 4, display: 'flex', justifyContent: 'center' }}>
|
|
98
|
-
<Tooltip {...args}>
|
|
99
|
-
<Button variant="contained" color="primary" data-testid="click-trigger">
|
|
100
|
-
Click me
|
|
101
|
-
</Button>
|
|
102
|
-
</Tooltip>
|
|
103
|
-
</Box>
|
|
104
|
-
),
|
|
105
|
-
play: async ({ canvasElement, step }) => {
|
|
106
|
-
const canvas = within(canvasElement);
|
|
107
|
-
|
|
108
|
-
await step('Click shows tooltip', async () => {
|
|
109
|
-
const button = canvas.getByTestId('click-trigger');
|
|
110
|
-
await userEvent.click(button);
|
|
111
|
-
|
|
112
|
-
await waitFor(
|
|
113
|
-
async () => {
|
|
114
|
-
const tooltip = await findTooltipByContent('Click tooltip');
|
|
115
|
-
await expect(tooltip).toBeInTheDocument();
|
|
116
|
-
await expect(tooltip).toHaveTextContent('Click tooltip');
|
|
117
|
-
},
|
|
118
|
-
{ timeout: 2000 },
|
|
119
|
-
);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
await step('Click elsewhere hides tooltip', async () => {
|
|
123
|
-
// Click outside the button
|
|
124
|
-
await userEvent.click(canvasElement);
|
|
125
|
-
|
|
126
|
-
await waitFor(
|
|
127
|
-
() => {
|
|
128
|
-
const tooltip = within(document.body).queryByRole('tooltip');
|
|
129
|
-
expect(tooltip).not.toBeInTheDocument();
|
|
130
|
-
},
|
|
131
|
-
{ timeout: 2000 },
|
|
132
|
-
);
|
|
133
|
-
});
|
|
134
|
-
},
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
const StateChangeTestComponent = () => {
|
|
138
|
-
const [variant, setVariant] = React.useState<'default' | 'dark' | 'light' | 'glass'>('default');
|
|
139
|
-
const [glow, setGlow] = React.useState(false);
|
|
140
|
-
const [pulse, setPulse] = React.useState(false);
|
|
141
|
-
|
|
142
|
-
return (
|
|
143
|
-
<Box sx={{ p: 4, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2 }}>
|
|
144
|
-
<Stack direction="row" spacing={2} sx={{ mb: 2 }}>
|
|
145
|
-
<Button
|
|
146
|
-
variant="outlined"
|
|
147
|
-
size="small"
|
|
148
|
-
onClick={() => setVariant(variant === 'default' ? 'dark' : 'default')}
|
|
149
|
-
data-testid="variant-toggle"
|
|
150
|
-
>
|
|
151
|
-
Toggle Variant
|
|
152
|
-
</Button>
|
|
153
|
-
<Button
|
|
154
|
-
variant="outlined"
|
|
155
|
-
size="small"
|
|
156
|
-
onClick={() => setGlow(!glow)}
|
|
157
|
-
data-testid="glow-toggle"
|
|
158
|
-
>
|
|
159
|
-
Toggle Glow
|
|
160
|
-
</Button>
|
|
161
|
-
<Button
|
|
162
|
-
variant="outlined"
|
|
163
|
-
size="small"
|
|
164
|
-
onClick={() => setPulse(!pulse)}
|
|
165
|
-
data-testid="pulse-toggle"
|
|
166
|
-
>
|
|
167
|
-
Toggle Pulse
|
|
168
|
-
</Button>
|
|
169
|
-
</Stack>
|
|
170
|
-
|
|
171
|
-
<Tooltip
|
|
172
|
-
title={`Variant: ${variant}, Glow: ${glow}, Pulse: ${pulse}`}
|
|
173
|
-
variant={variant}
|
|
174
|
-
glow={glow}
|
|
175
|
-
pulse={pulse}
|
|
176
|
-
>
|
|
177
|
-
<Button variant="contained" data-testid="stateful-tooltip">
|
|
178
|
-
Dynamic Tooltip
|
|
179
|
-
</Button>
|
|
180
|
-
</Tooltip>
|
|
181
|
-
</Box>
|
|
182
|
-
);
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
export const StateChangeTest: Story = {
|
|
186
|
-
name: '🔄 State Change Test',
|
|
187
|
-
render: () => <StateChangeTestComponent />,
|
|
188
|
-
play: async ({ canvasElement, step }) => {
|
|
189
|
-
const canvas = within(canvasElement);
|
|
190
|
-
|
|
191
|
-
await step('Toggle variant changes tooltip style', async () => {
|
|
192
|
-
const variantButton = canvas.getByTestId('variant-toggle');
|
|
193
|
-
const tooltipTrigger = canvas.getByTestId('stateful-tooltip');
|
|
194
|
-
|
|
195
|
-
await userEvent.click(variantButton);
|
|
196
|
-
await userEvent.hover(tooltipTrigger);
|
|
197
|
-
|
|
198
|
-
await waitFor(
|
|
199
|
-
async () => {
|
|
200
|
-
const tooltip = await findTooltipByContent();
|
|
201
|
-
await expect(tooltip).toBeInTheDocument();
|
|
202
|
-
await expect(tooltip).toHaveTextContent(/dark/);
|
|
203
|
-
},
|
|
204
|
-
{ timeout: 2000 },
|
|
205
|
-
);
|
|
206
|
-
|
|
207
|
-
await userEvent.unhover(tooltipTrigger);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
await step('Toggle glow adds visual effect', async () => {
|
|
211
|
-
const glowButton = canvas.getByTestId('glow-toggle');
|
|
212
|
-
const tooltipTrigger = canvas.getByTestId('stateful-tooltip');
|
|
213
|
-
|
|
214
|
-
await userEvent.click(glowButton);
|
|
215
|
-
await userEvent.hover(tooltipTrigger);
|
|
216
|
-
|
|
217
|
-
await waitFor(
|
|
218
|
-
async () => {
|
|
219
|
-
const tooltip = await findTooltipByContent();
|
|
220
|
-
await expect(tooltip).toHaveTextContent(/Glow: true/);
|
|
221
|
-
},
|
|
222
|
-
{ timeout: 2000 },
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
await userEvent.unhover(tooltipTrigger);
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
await step('Toggle pulse adds animation', async () => {
|
|
229
|
-
const pulseButton = canvas.getByTestId('pulse-toggle');
|
|
230
|
-
const tooltipTrigger = canvas.getByTestId('stateful-tooltip');
|
|
231
|
-
|
|
232
|
-
await userEvent.click(pulseButton);
|
|
233
|
-
await userEvent.hover(tooltipTrigger);
|
|
234
|
-
|
|
235
|
-
await waitFor(
|
|
236
|
-
async () => {
|
|
237
|
-
const tooltip = await findTooltipByContent();
|
|
238
|
-
await expect(tooltip).toHaveTextContent(/Pulse: true/);
|
|
239
|
-
},
|
|
240
|
-
{ timeout: 2000 },
|
|
241
|
-
);
|
|
242
|
-
|
|
243
|
-
await userEvent.unhover(tooltipTrigger);
|
|
244
|
-
});
|
|
245
|
-
},
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
// 7.3 Accessibility Tests
|
|
249
|
-
export const KeyboardNavigation: Story = {
|
|
250
|
-
name: '⌨️ Keyboard Navigation Test',
|
|
251
|
-
parameters: {
|
|
252
|
-
a11y: {
|
|
253
|
-
element: '#storybook-root',
|
|
254
|
-
config: {
|
|
255
|
-
rules: [
|
|
256
|
-
{ id: 'color-contrast', enabled: true },
|
|
257
|
-
{ id: 'aria-required-attr', enabled: true },
|
|
258
|
-
{ id: 'aria-roles', enabled: true },
|
|
259
|
-
{ id: 'aria-valid-attr-value', enabled: true },
|
|
260
|
-
{ id: 'button-name', enabled: true },
|
|
261
|
-
{ id: 'duplicate-id', enabled: true },
|
|
262
|
-
{ id: 'label', enabled: true },
|
|
263
|
-
],
|
|
264
|
-
},
|
|
265
|
-
},
|
|
266
|
-
},
|
|
267
|
-
render: () => (
|
|
268
|
-
<Box sx={{ p: 4, display: 'flex', justifyContent: 'center', gap: 2 }}>
|
|
269
|
-
<Stack direction="row" spacing={2}>
|
|
270
|
-
<Tooltip title="First tooltip" variant="default">
|
|
271
|
-
<Button variant="outlined" data-testid="first-focusable">
|
|
272
|
-
First
|
|
273
|
-
</Button>
|
|
274
|
-
</Tooltip>
|
|
275
|
-
|
|
276
|
-
<Tooltip title="Second tooltip" variant="light">
|
|
277
|
-
<Button variant="outlined" data-testid="second-focusable">
|
|
278
|
-
Second
|
|
279
|
-
</Button>
|
|
280
|
-
</Tooltip>
|
|
281
|
-
|
|
282
|
-
<Tooltip title="Third tooltip with keyboard navigation" variant="glass">
|
|
283
|
-
<IconButton data-testid="third-focusable">
|
|
284
|
-
<Help />
|
|
285
|
-
</IconButton>
|
|
286
|
-
</Tooltip>
|
|
287
|
-
</Stack>
|
|
288
|
-
</Box>
|
|
289
|
-
),
|
|
290
|
-
play: async ({ canvasElement, step }) => {
|
|
291
|
-
const canvas = within(canvasElement);
|
|
292
|
-
|
|
293
|
-
await step('Tab navigation forward', async () => {
|
|
294
|
-
const firstElement = canvas.getByTestId('first-focusable');
|
|
295
|
-
const secondElement = canvas.getByTestId('second-focusable');
|
|
296
|
-
|
|
297
|
-
// Tab in from the body rather than calling .focus().
|
|
298
|
-
await userEvent.tab();
|
|
299
|
-
await waitFor(() => expect(firstElement).toHaveFocus());
|
|
300
|
-
|
|
301
|
-
// Tab to next element
|
|
302
|
-
await userEvent.tab();
|
|
303
|
-
await waitFor(() => expect(secondElement).toHaveFocus());
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
await step('Tab navigation backward', async () => {
|
|
307
|
-
await userEvent.tab({ shift: true });
|
|
308
|
-
const firstElement = canvas.getByTestId('first-focusable');
|
|
309
|
-
await waitFor(() => expect(firstElement).toHaveFocus());
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
await step('Enter key maintains focus', async () => {
|
|
313
|
-
const firstButton = canvas.getByTestId('first-focusable');
|
|
314
|
-
// Focus is already back here from the shift-tab in the previous step.
|
|
315
|
-
await waitFor(() => expect(firstButton).toHaveFocus());
|
|
316
|
-
await userEvent.keyboard('{Enter}');
|
|
317
|
-
await waitFor(() => expect(firstButton).toHaveFocus());
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
await step('Space key maintains focus', async () => {
|
|
321
|
-
const secondButton = canvas.getByTestId('second-focusable');
|
|
322
|
-
await userEvent.tab();
|
|
323
|
-
await waitFor(() => expect(secondButton).toHaveFocus());
|
|
324
|
-
await userEvent.keyboard(' ');
|
|
325
|
-
await waitFor(() => expect(secondButton).toHaveFocus());
|
|
326
|
-
});
|
|
327
|
-
},
|
|
328
|
-
};
|
|
329
|
-
|
|
330
|
-
export const ScreenReaderTest: Story = {
|
|
331
|
-
name: '🔊 Screen Reader Test',
|
|
332
|
-
render: () => (
|
|
333
|
-
<Box sx={{ p: 4, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3 }}>
|
|
334
|
-
<Tooltip title="This tooltip provides additional context" variant="default">
|
|
335
|
-
<Button data-testid="aria-component" aria-label="Action button with tooltip">
|
|
336
|
-
Action
|
|
337
|
-
</Button>
|
|
338
|
-
</Tooltip>
|
|
339
|
-
|
|
340
|
-
<Tooltip title="Delete this item permanently" variant="dark" placement="top">
|
|
341
|
-
<IconButton data-testid="delete-button" aria-label="Delete item" color="error">
|
|
342
|
-
<Delete />
|
|
343
|
-
</IconButton>
|
|
344
|
-
</Tooltip>
|
|
345
|
-
|
|
346
|
-
<Box>
|
|
347
|
-
<Typography variant="subtitle2" id="field-label" data-testid="field-label" sx={{ mb: 1 }}>
|
|
348
|
-
Important Setting
|
|
349
|
-
</Typography>
|
|
350
|
-
<Tooltip
|
|
351
|
-
title="This setting affects system performance and cannot be changed later"
|
|
352
|
-
variant="light"
|
|
353
|
-
placement="right"
|
|
354
|
-
>
|
|
355
|
-
<IconButton
|
|
356
|
-
data-testid="help-icon"
|
|
357
|
-
aria-label="Help information for important setting"
|
|
358
|
-
aria-describedby="field-label"
|
|
359
|
-
size="small"
|
|
360
|
-
>
|
|
361
|
-
<Info fontSize="small" />
|
|
362
|
-
</IconButton>
|
|
363
|
-
</Tooltip>
|
|
364
|
-
</Box>
|
|
365
|
-
</Box>
|
|
366
|
-
),
|
|
367
|
-
play: async ({ canvasElement, step }) => {
|
|
368
|
-
const canvas = within(canvasElement);
|
|
369
|
-
|
|
370
|
-
await step('Verify ARIA labels', async () => {
|
|
371
|
-
const actionButton = canvas.getByTestId('aria-component');
|
|
372
|
-
await expect(actionButton).toHaveAttribute('aria-label', 'Action button with tooltip');
|
|
373
|
-
|
|
374
|
-
const deleteButton = canvas.getByTestId('delete-button');
|
|
375
|
-
await expect(deleteButton).toHaveAttribute('aria-label', 'Delete item');
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
await step('Verify ARIA descriptions', async () => {
|
|
379
|
-
const helpIcon = canvas.getByTestId('help-icon');
|
|
380
|
-
await expect(helpIcon).toHaveAttribute('aria-describedby', 'field-label');
|
|
381
|
-
|
|
382
|
-
const label = canvas.getByTestId('field-label') || canvas.getByText('Important Setting');
|
|
383
|
-
await expect(label).toBeInTheDocument();
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
await step('Verify tooltip content is accessible', async () => {
|
|
387
|
-
const actionButton = canvas.getByTestId('aria-component');
|
|
388
|
-
await userEvent.hover(actionButton);
|
|
389
|
-
|
|
390
|
-
await waitFor(
|
|
391
|
-
async () => {
|
|
392
|
-
const tooltip = await findTooltipByContent();
|
|
393
|
-
await expect(tooltip).toBeInTheDocument();
|
|
394
|
-
await expect(tooltip).toHaveTextContent('This tooltip provides additional context');
|
|
395
|
-
},
|
|
396
|
-
{ timeout: 2000 },
|
|
397
|
-
);
|
|
398
|
-
|
|
399
|
-
await userEvent.unhover(actionButton);
|
|
400
|
-
});
|
|
401
|
-
},
|
|
402
|
-
};
|
|
403
|
-
|
|
404
|
-
export const FocusManagement: Story = {
|
|
405
|
-
name: '🎯 Focus Management Test',
|
|
406
|
-
render: () => (
|
|
407
|
-
<Box sx={{ p: 4, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3 }}>
|
|
408
|
-
<Tooltip title="Focus is maintained on trigger" variant="default">
|
|
409
|
-
<Button data-testid="focus-trigger" variant="contained" autoFocus>
|
|
410
|
-
Auto Focus Button
|
|
411
|
-
</Button>
|
|
412
|
-
</Tooltip>
|
|
413
|
-
|
|
414
|
-
<Stack direction="row" spacing={2}>
|
|
415
|
-
<Tooltip title="First focusable element" variant="light">
|
|
416
|
-
<Button data-testid="first-element">First</Button>
|
|
417
|
-
</Tooltip>
|
|
418
|
-
|
|
419
|
-
<Tooltip title="Second focusable element" variant="glass">
|
|
420
|
-
<Button data-testid="second-element">Second</Button>
|
|
421
|
-
</Tooltip>
|
|
422
|
-
|
|
423
|
-
<Tooltip title="Last focusable element" variant="dark">
|
|
424
|
-
<Button data-testid="last-element">Last</Button>
|
|
425
|
-
</Tooltip>
|
|
426
|
-
</Stack>
|
|
427
|
-
</Box>
|
|
428
|
-
),
|
|
429
|
-
play: async ({ canvasElement, step }) => {
|
|
430
|
-
const canvas = within(canvasElement);
|
|
431
|
-
|
|
432
|
-
await step('Auto focus on mount', async () => {
|
|
433
|
-
const autoFocusElement = canvas.getByTestId('focus-trigger');
|
|
434
|
-
await waitFor(() => {
|
|
435
|
-
expect(autoFocusElement).toHaveFocus();
|
|
436
|
-
});
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
await step('Focus is maintained during tooltip display', async () => {
|
|
440
|
-
const focusButton = canvas.getByTestId('focus-trigger');
|
|
441
|
-
await userEvent.tab();
|
|
442
|
-
await waitFor(() => expect(focusButton).toHaveFocus());
|
|
443
|
-
|
|
444
|
-
// Hover to show tooltip
|
|
445
|
-
await userEvent.hover(focusButton);
|
|
446
|
-
|
|
447
|
-
await waitFor(
|
|
448
|
-
async () => {
|
|
449
|
-
const tooltip = await findTooltipByContent();
|
|
450
|
-
await expect(tooltip).toBeInTheDocument();
|
|
451
|
-
// Focus should remain on trigger
|
|
452
|
-
await waitFor(() => expect(focusButton).toHaveFocus());
|
|
453
|
-
},
|
|
454
|
-
{ timeout: 2000 },
|
|
455
|
-
);
|
|
456
|
-
|
|
457
|
-
await userEvent.unhover(focusButton);
|
|
458
|
-
});
|
|
459
|
-
|
|
460
|
-
await step('Tab order is preserved', async () => {
|
|
461
|
-
const firstElement = canvas.getByTestId('first-element');
|
|
462
|
-
const secondElement = canvas.getByTestId('second-element');
|
|
463
|
-
const lastElement = canvas.getByTestId('last-element');
|
|
464
|
-
|
|
465
|
-
await userEvent.tab();
|
|
466
|
-
await waitFor(() => expect(firstElement).toHaveFocus());
|
|
467
|
-
|
|
468
|
-
await userEvent.tab();
|
|
469
|
-
await waitFor(() => expect(secondElement).toHaveFocus());
|
|
470
|
-
|
|
471
|
-
await userEvent.tab();
|
|
472
|
-
await waitFor(() => expect(lastElement).toHaveFocus());
|
|
473
|
-
});
|
|
474
|
-
},
|
|
475
|
-
};
|
|
476
|
-
|
|
477
|
-
// 7.4 Visual Tests
|
|
478
|
-
export const ResponsiveDesign: Story = {
|
|
479
|
-
name: '📱 Responsive Design Test',
|
|
480
|
-
parameters: {
|
|
481
|
-
viewport: {
|
|
482
|
-
viewports: {
|
|
483
|
-
mobile: {
|
|
484
|
-
name: 'Mobile',
|
|
485
|
-
styles: { width: '375px', height: '667px' },
|
|
486
|
-
type: 'mobile',
|
|
487
|
-
},
|
|
488
|
-
tablet: {
|
|
489
|
-
name: 'Tablet',
|
|
490
|
-
styles: { width: '768px', height: '1024px' },
|
|
491
|
-
type: 'tablet',
|
|
492
|
-
},
|
|
493
|
-
desktop: {
|
|
494
|
-
name: 'Desktop',
|
|
495
|
-
styles: { width: '1920px', height: '1080px' },
|
|
496
|
-
type: 'desktop',
|
|
497
|
-
},
|
|
498
|
-
},
|
|
499
|
-
defaultViewport: 'mobile',
|
|
500
|
-
},
|
|
501
|
-
chromatic: {
|
|
502
|
-
viewports: [375, 768, 1920],
|
|
503
|
-
delay: 300,
|
|
504
|
-
},
|
|
505
|
-
},
|
|
506
|
-
render: () => (
|
|
507
|
-
<Box
|
|
508
|
-
sx={{
|
|
509
|
-
p: 2,
|
|
510
|
-
display: 'flex',
|
|
511
|
-
flexDirection: { xs: 'column', md: 'row' },
|
|
512
|
-
gap: 2,
|
|
513
|
-
justifyContent: 'center',
|
|
514
|
-
alignItems: 'center',
|
|
515
|
-
}}
|
|
516
|
-
data-testid="responsive-container"
|
|
517
|
-
>
|
|
518
|
-
<Tooltip
|
|
519
|
-
title="This tooltip adapts to different screen sizes and viewport widths"
|
|
520
|
-
variant="default"
|
|
521
|
-
maxWidth={200}
|
|
522
|
-
>
|
|
523
|
-
<Button variant="outlined" size="small">
|
|
524
|
-
Mobile Tooltip
|
|
525
|
-
</Button>
|
|
526
|
-
</Tooltip>
|
|
527
|
-
|
|
528
|
-
<Tooltip
|
|
529
|
-
title="Tablet and desktop tooltip with more content that demonstrates responsive behavior"
|
|
530
|
-
variant="light"
|
|
531
|
-
maxWidth={300}
|
|
532
|
-
>
|
|
533
|
-
<Button variant="outlined">Responsive Tooltip</Button>
|
|
534
|
-
</Tooltip>
|
|
535
|
-
</Box>
|
|
536
|
-
),
|
|
537
|
-
play: async ({ canvasElement, step }) => {
|
|
538
|
-
const canvas = within(canvasElement);
|
|
539
|
-
|
|
540
|
-
await step('Verify responsive container layout', async () => {
|
|
541
|
-
const container = canvas.getByTestId('responsive-container');
|
|
542
|
-
await expect(container).toBeInTheDocument();
|
|
543
|
-
|
|
544
|
-
// Assert the container has an explicit flex direction, without branching
|
|
545
|
-
// on the runner's window width. Reading innerWidth made the story assert a
|
|
546
|
-
// different thing depending on the machine it ran on, so neither branch
|
|
547
|
-
// was ever exercised in both directions.
|
|
548
|
-
const computedStyle = window.getComputedStyle(container);
|
|
549
|
-
await expect(['row', 'column']).toContain(computedStyle.flexDirection);
|
|
550
|
-
});
|
|
551
|
-
|
|
552
|
-
await step('Test tooltip rendering at different viewport sizes', async () => {
|
|
553
|
-
const buttons = canvas.getAllByRole('button');
|
|
554
|
-
|
|
555
|
-
for (const button of buttons) {
|
|
556
|
-
await userEvent.hover(button);
|
|
557
|
-
|
|
558
|
-
await waitFor(
|
|
559
|
-
async () => {
|
|
560
|
-
const tooltip = await findTooltipByContent();
|
|
561
|
-
await expect(tooltip).toBeInTheDocument();
|
|
562
|
-
},
|
|
563
|
-
{ timeout: 2000 },
|
|
564
|
-
);
|
|
565
|
-
|
|
566
|
-
await userEvent.unhover(button);
|
|
567
|
-
}
|
|
568
|
-
});
|
|
569
|
-
},
|
|
570
|
-
};
|
|
571
|
-
|
|
572
|
-
export const ThemeVariations: Story = {
|
|
573
|
-
name: '🎨 Theme Variations Test',
|
|
574
|
-
parameters: {
|
|
575
|
-
backgrounds: {
|
|
576
|
-
default: 'light',
|
|
577
|
-
values: [
|
|
578
|
-
{ name: 'light', value: '#ffffff' },
|
|
579
|
-
{ name: 'dark', value: '#1a1a1a' },
|
|
580
|
-
{ name: 'gray', value: '#f5f5f5' },
|
|
581
|
-
],
|
|
582
|
-
},
|
|
583
|
-
},
|
|
584
|
-
render: () => (
|
|
585
|
-
<Box sx={{ p: 4, display: 'flex', flexDirection: 'column', gap: 3, alignItems: 'center' }}>
|
|
586
|
-
<Stack direction="row" spacing={2}>
|
|
587
|
-
<Tooltip title="Default theme" variant="default">
|
|
588
|
-
<Button variant="outlined" data-testid="default-theme">
|
|
589
|
-
Default
|
|
590
|
-
</Button>
|
|
591
|
-
</Tooltip>
|
|
592
|
-
|
|
593
|
-
<Tooltip title="Light theme" variant="light">
|
|
594
|
-
<Button variant="outlined" data-testid="light-theme">
|
|
595
|
-
Light
|
|
596
|
-
</Button>
|
|
597
|
-
</Tooltip>
|
|
598
|
-
|
|
599
|
-
<Tooltip title="Dark theme" variant="dark">
|
|
600
|
-
<Button variant="outlined" data-testid="dark-theme">
|
|
601
|
-
Dark
|
|
602
|
-
</Button>
|
|
603
|
-
</Tooltip>
|
|
604
|
-
|
|
605
|
-
<Tooltip title="Glass theme" variant="glass">
|
|
606
|
-
<Button variant="outlined" data-testid="glass-theme">
|
|
607
|
-
Glass
|
|
608
|
-
</Button>
|
|
609
|
-
</Tooltip>
|
|
610
|
-
</Stack>
|
|
611
|
-
|
|
612
|
-
<Stack direction="row" spacing={2}>
|
|
613
|
-
<Tooltip title="Glow effect" variant="default" glow>
|
|
614
|
-
<Button variant="contained" color="primary" data-testid="glow-effect">
|
|
615
|
-
Glow
|
|
616
|
-
</Button>
|
|
617
|
-
</Tooltip>
|
|
618
|
-
|
|
619
|
-
<Tooltip title="Pulse animation" variant="light" pulse>
|
|
620
|
-
<Button variant="contained" color="secondary" data-testid="pulse-effect">
|
|
621
|
-
Pulse
|
|
622
|
-
</Button>
|
|
623
|
-
</Tooltip>
|
|
624
|
-
|
|
625
|
-
<Tooltip title="Combined effects" variant="glass" glow pulse>
|
|
626
|
-
<Button variant="contained" color="success" data-testid="combined-effects">
|
|
627
|
-
Combined
|
|
628
|
-
</Button>
|
|
629
|
-
</Tooltip>
|
|
630
|
-
</Stack>
|
|
631
|
-
</Box>
|
|
632
|
-
),
|
|
633
|
-
play: async ({ canvasElement, step }) => {
|
|
634
|
-
const canvas = within(canvasElement);
|
|
635
|
-
|
|
636
|
-
await step('Verify all theme variants render', async () => {
|
|
637
|
-
const buttons = ['default-theme', 'light-theme', 'dark-theme', 'glass-theme'];
|
|
638
|
-
|
|
639
|
-
for (const buttonId of buttons) {
|
|
640
|
-
const button = canvas.getByTestId(buttonId);
|
|
641
|
-
await userEvent.hover(button);
|
|
642
|
-
|
|
643
|
-
await waitFor(
|
|
644
|
-
async () => {
|
|
645
|
-
const tooltip = await findTooltipByContent();
|
|
646
|
-
await expect(tooltip).toBeInTheDocument();
|
|
647
|
-
},
|
|
648
|
-
{ timeout: 2000 },
|
|
649
|
-
);
|
|
650
|
-
|
|
651
|
-
await userEvent.unhover(button);
|
|
652
|
-
}
|
|
653
|
-
});
|
|
654
|
-
|
|
655
|
-
await step('Verify visual effects render', async () => {
|
|
656
|
-
const effectButtons = ['glow-effect', 'pulse-effect', 'combined-effects'];
|
|
657
|
-
|
|
658
|
-
for (const buttonId of effectButtons) {
|
|
659
|
-
const button = canvas.getByTestId(buttonId);
|
|
660
|
-
await userEvent.hover(button);
|
|
661
|
-
|
|
662
|
-
await waitFor(
|
|
663
|
-
async () => {
|
|
664
|
-
const tooltip = await findTooltipByContent();
|
|
665
|
-
await expect(tooltip).toBeInTheDocument();
|
|
666
|
-
},
|
|
667
|
-
{ timeout: 2000 },
|
|
668
|
-
);
|
|
669
|
-
|
|
670
|
-
await userEvent.unhover(button);
|
|
671
|
-
}
|
|
672
|
-
});
|
|
673
|
-
},
|
|
674
|
-
};
|
|
675
|
-
|
|
676
|
-
export const VisualStates: Story = {
|
|
677
|
-
name: '👁️ Visual States Test',
|
|
678
|
-
render: () => (
|
|
679
|
-
<Box sx={{ p: 4, display: 'flex', flexDirection: 'column', gap: 3, alignItems: 'center' }}>
|
|
680
|
-
<Stack direction="row" spacing={2}>
|
|
681
|
-
<Tooltip title="Normal state tooltip">
|
|
682
|
-
<Button variant="outlined" data-testid="normal-state">
|
|
683
|
-
Normal
|
|
684
|
-
</Button>
|
|
685
|
-
</Tooltip>
|
|
686
|
-
|
|
687
|
-
<Tooltip title="This button is disabled" placement="top">
|
|
688
|
-
<span>
|
|
689
|
-
<Button variant="outlined" disabled data-testid="disabled-button">
|
|
690
|
-
Disabled
|
|
691
|
-
</Button>
|
|
692
|
-
</span>
|
|
693
|
-
</Tooltip>
|
|
694
|
-
</Stack>
|
|
695
|
-
|
|
696
|
-
<Stack direction="row" spacing={2}>
|
|
697
|
-
<Tooltip title="Small size tooltip" size="sm">
|
|
698
|
-
<Button variant="outlined" size="small" data-testid="small-tooltip">
|
|
699
|
-
Small
|
|
700
|
-
</Button>
|
|
701
|
-
</Tooltip>
|
|
702
|
-
|
|
703
|
-
<Tooltip title="Large size tooltip" size="lg">
|
|
704
|
-
<Button variant="outlined" size="large" data-testid="large-tooltip">
|
|
705
|
-
Large
|
|
706
|
-
</Button>
|
|
707
|
-
</Tooltip>
|
|
708
|
-
</Stack>
|
|
709
|
-
|
|
710
|
-
<Tooltip
|
|
711
|
-
title="This is a very long tooltip text that should wrap properly within the maximum width constraints and demonstrate how the tooltip handles lengthy content gracefully"
|
|
712
|
-
maxWidth={200}
|
|
713
|
-
>
|
|
714
|
-
<Button variant="outlined" data-testid="long-text-tooltip">
|
|
715
|
-
Long Text
|
|
716
|
-
</Button>
|
|
717
|
-
</Tooltip>
|
|
718
|
-
</Box>
|
|
719
|
-
),
|
|
720
|
-
play: async ({ canvasElement, step }) => {
|
|
721
|
-
const canvas = within(canvasElement);
|
|
722
|
-
|
|
723
|
-
await step('Normal state tooltip', async () => {
|
|
724
|
-
const button = canvas.getByTestId('normal-state');
|
|
725
|
-
await userEvent.hover(button);
|
|
726
|
-
|
|
727
|
-
await waitFor(
|
|
728
|
-
async () => {
|
|
729
|
-
const tooltip = await findTooltipByContent();
|
|
730
|
-
await expect(tooltip).toBeInTheDocument();
|
|
731
|
-
await expect(tooltip).toHaveTextContent('Normal state tooltip');
|
|
732
|
-
},
|
|
733
|
-
{ timeout: 2000 },
|
|
734
|
-
);
|
|
735
|
-
|
|
736
|
-
await userEvent.unhover(button);
|
|
737
|
-
});
|
|
738
|
-
|
|
739
|
-
await step('Disabled state tooltip', async () => {
|
|
740
|
-
const disabledButton = canvas.getByTestId('disabled-button');
|
|
741
|
-
await expect(disabledButton).toBeDisabled();
|
|
742
|
-
|
|
743
|
-
// Hover on the span wrapper since disabled buttons don't receive hover events
|
|
744
|
-
const wrapper = disabledButton.parentElement;
|
|
745
|
-
if (wrapper) {
|
|
746
|
-
await userEvent.hover(wrapper);
|
|
747
|
-
|
|
748
|
-
await waitFor(
|
|
749
|
-
async () => {
|
|
750
|
-
const tooltip = await findTooltipByContent();
|
|
751
|
-
await expect(tooltip).toHaveTextContent('This button is disabled');
|
|
752
|
-
},
|
|
753
|
-
{ timeout: 2000 },
|
|
754
|
-
);
|
|
755
|
-
|
|
756
|
-
await userEvent.unhover(wrapper);
|
|
757
|
-
}
|
|
758
|
-
});
|
|
759
|
-
|
|
760
|
-
await step('Different sizes render correctly', async () => {
|
|
761
|
-
const smallButton = canvas.getByTestId('small-tooltip');
|
|
762
|
-
await userEvent.hover(smallButton);
|
|
763
|
-
|
|
764
|
-
await waitFor(
|
|
765
|
-
async () => {
|
|
766
|
-
const tooltip = await findTooltipByContent();
|
|
767
|
-
await expect(tooltip).toHaveTextContent('Small size tooltip');
|
|
768
|
-
},
|
|
769
|
-
{ timeout: 2000 },
|
|
770
|
-
);
|
|
771
|
-
|
|
772
|
-
await userEvent.unhover(smallButton);
|
|
773
|
-
|
|
774
|
-
const largeButton = canvas.getByTestId('large-tooltip');
|
|
775
|
-
await userEvent.hover(largeButton);
|
|
776
|
-
|
|
777
|
-
await waitFor(
|
|
778
|
-
async () => {
|
|
779
|
-
const tooltip = await findTooltipByContent();
|
|
780
|
-
await expect(tooltip).toHaveTextContent('Large size tooltip');
|
|
781
|
-
},
|
|
782
|
-
{ timeout: 2000 },
|
|
783
|
-
);
|
|
784
|
-
|
|
785
|
-
await userEvent.unhover(largeButton);
|
|
786
|
-
});
|
|
787
|
-
|
|
788
|
-
await step('Long text wrapping', async () => {
|
|
789
|
-
const longTextButton = canvas.getByTestId('long-text-tooltip');
|
|
790
|
-
await userEvent.hover(longTextButton);
|
|
791
|
-
|
|
792
|
-
await waitFor(
|
|
793
|
-
async () => {
|
|
794
|
-
const tooltip = await findTooltipByContent();
|
|
795
|
-
await expect(tooltip).toBeInTheDocument();
|
|
796
|
-
// Check that tooltip contains the long text
|
|
797
|
-
await expect(tooltip).toHaveTextContent(/very long tooltip text/);
|
|
798
|
-
},
|
|
799
|
-
{ timeout: 2000 },
|
|
800
|
-
);
|
|
801
|
-
|
|
802
|
-
await userEvent.unhover(longTextButton);
|
|
803
|
-
});
|
|
804
|
-
},
|
|
805
|
-
};
|
|
806
|
-
|
|
807
|
-
// 7.5 Performance Tests
|
|
808
|
-
export const PerformanceTest: Story = {
|
|
809
|
-
name: '⚡ Performance Test',
|
|
810
|
-
render: () => {
|
|
811
|
-
const items = Array.from({ length: 20 }, (_, i) => ({
|
|
812
|
-
id: i,
|
|
813
|
-
name: `Item ${i}`,
|
|
814
|
-
description: `Description for item ${i} with additional context information`,
|
|
815
|
-
}));
|
|
816
|
-
|
|
817
|
-
return (
|
|
818
|
-
<Box sx={{ p: 2, maxHeight: 400, overflow: 'auto' }} data-testid="scroll-container">
|
|
819
|
-
<Stack spacing={1}>
|
|
820
|
-
{items.map((item) => (
|
|
821
|
-
<Tooltip key={item.id} title={item.description} variant="default" placement="right">
|
|
822
|
-
<Button
|
|
823
|
-
variant="outlined"
|
|
824
|
-
size="small"
|
|
825
|
-
fullWidth
|
|
826
|
-
data-testid={`item-${item.id}`}
|
|
827
|
-
sx={{ justifyContent: 'flex-start' }}
|
|
828
|
-
>
|
|
829
|
-
{item.name}
|
|
830
|
-
</Button>
|
|
831
|
-
</Tooltip>
|
|
832
|
-
))}
|
|
833
|
-
</Stack>
|
|
834
|
-
</Box>
|
|
835
|
-
);
|
|
836
|
-
},
|
|
837
|
-
play: async ({ canvasElement, step }) => {
|
|
838
|
-
const canvas = within(canvasElement);
|
|
839
|
-
|
|
840
|
-
await step('Measure render time for multiple tooltips', async () => {
|
|
841
|
-
// No wall-clock budget: this queries DOM that has already rendered, so the
|
|
842
|
-
// timing measured query cost and any threshold tracks runner load.
|
|
843
|
-
const elements = canvas.getAllByTestId(/item-/);
|
|
844
|
-
await expect(elements.length).toBe(20);
|
|
845
|
-
});
|
|
846
|
-
|
|
847
|
-
await step('Test rapid tooltip interactions', async () => {
|
|
848
|
-
const elements = canvas.getAllByTestId(/item-/);
|
|
849
|
-
const testElements = elements.slice(0, 5); // Test first 5 items
|
|
850
|
-
|
|
851
|
-
// Hover and unhover each in turn. The 50ms sleep between them was a guess
|
|
852
|
-
// at how long the tooltip needs; the elements surviving the cycle is the
|
|
853
|
-
// property this step actually cares about.
|
|
854
|
-
for (const element of testElements) {
|
|
855
|
-
await userEvent.hover(element);
|
|
856
|
-
await userEvent.unhover(element);
|
|
857
|
-
await expect(element).toBeInTheDocument();
|
|
858
|
-
}
|
|
859
|
-
});
|
|
860
|
-
|
|
861
|
-
await step('Tooltips still work inside a scroll container', async () => {
|
|
862
|
-
const scrollContainer = canvas.getByTestId('scroll-container');
|
|
863
|
-
await expect(scrollContainer).toBeInTheDocument();
|
|
864
|
-
|
|
865
|
-
// Driving scrollTop is not asserted on here. Whether the container scrolls
|
|
866
|
-
// at all depends on how tall the runner's window is, so a scrollTop check
|
|
867
|
-
// reports window size rather than component behaviour — and the original
|
|
868
|
-
// version wrapped it in a 500ms budget on top of that. What this step can
|
|
869
|
-
// honestly assert is that a tooltip trigger inside the container still
|
|
870
|
-
// responds to hover.
|
|
871
|
-
const [firstItem] = canvas.getAllByTestId(/item-/);
|
|
872
|
-
await userEvent.hover(firstItem);
|
|
873
|
-
await userEvent.unhover(firstItem);
|
|
874
|
-
await expect(firstItem).toBeInTheDocument();
|
|
875
|
-
});
|
|
876
|
-
},
|
|
877
|
-
};
|
|
878
|
-
|
|
879
|
-
// 7.6 Edge Cases Tests
|
|
880
|
-
export const EdgeCases: Story = {
|
|
881
|
-
name: '🔧 Edge Cases Test',
|
|
882
|
-
render: () => (
|
|
883
|
-
<Box sx={{ p: 4, display: 'flex', flexDirection: 'column', gap: 3, alignItems: 'center' }}>
|
|
884
|
-
<Tooltip title="" variant="default">
|
|
885
|
-
<Button variant="outlined" data-testid="empty-tooltip">
|
|
886
|
-
Empty Tooltip
|
|
887
|
-
</Button>
|
|
888
|
-
</Tooltip>
|
|
889
|
-
|
|
890
|
-
<Tooltip
|
|
891
|
-
title="This is an extremely long tooltip text that contains a lot of information and should properly handle the maximum width constraints while maintaining readability and proper text wrapping behavior even with very lengthy content that might otherwise cause layout issues or performance problems in less robust implementations"
|
|
892
|
-
maxWidth={150}
|
|
893
|
-
variant="light"
|
|
894
|
-
>
|
|
895
|
-
<Button variant="outlined" data-testid="very-long-text">
|
|
896
|
-
Very Long Text
|
|
897
|
-
</Button>
|
|
898
|
-
</Tooltip>
|
|
899
|
-
|
|
900
|
-
<Tooltip title={'Special chars: !@#$%^&*()_+{}|:<>?[];\'"\\,./`~'} variant="glass">
|
|
901
|
-
<Button variant="outlined" data-testid="special-chars">
|
|
902
|
-
Special Characters
|
|
903
|
-
</Button>
|
|
904
|
-
</Tooltip>
|
|
905
|
-
|
|
906
|
-
<Tooltip
|
|
907
|
-
title="HTML content test: <script>alert('test')</script> & entities: <>&"
|
|
908
|
-
variant="dark"
|
|
909
|
-
>
|
|
910
|
-
<Button variant="outlined" data-testid="html-content">
|
|
911
|
-
HTML Content
|
|
912
|
-
</Button>
|
|
913
|
-
</Tooltip>
|
|
914
|
-
|
|
915
|
-
<Tooltip title={0 as unknown as string} variant="default">
|
|
916
|
-
<Button variant="outlined" data-testid="invalid-props">
|
|
917
|
-
Invalid Props
|
|
918
|
-
</Button>
|
|
919
|
-
</Tooltip>
|
|
920
|
-
</Box>
|
|
921
|
-
),
|
|
922
|
-
play: async ({ canvasElement, step }) => {
|
|
923
|
-
const canvas = within(canvasElement);
|
|
924
|
-
|
|
925
|
-
await step('Empty content handling', async () => {
|
|
926
|
-
const emptyButton = canvas.getByTestId('empty-tooltip');
|
|
927
|
-
await userEvent.hover(emptyButton);
|
|
928
|
-
|
|
929
|
-
// Should handle empty tooltip gracefully (might not show or show empty)
|
|
930
|
-
await new Promise((resolve) => window.setTimeout(resolve, 500));
|
|
931
|
-
|
|
932
|
-
await userEvent.unhover(emptyButton);
|
|
933
|
-
});
|
|
934
|
-
|
|
935
|
-
await step('Very long text overflow handling', async () => {
|
|
936
|
-
const longTextButton = canvas.getByTestId('very-long-text');
|
|
937
|
-
await userEvent.hover(longTextButton);
|
|
938
|
-
|
|
939
|
-
await waitFor(
|
|
940
|
-
async () => {
|
|
941
|
-
const tooltip = await findTooltipByContent();
|
|
942
|
-
await expect(tooltip).toBeInTheDocument();
|
|
943
|
-
// Should contain the long text but be constrained by maxWidth
|
|
944
|
-
await expect(tooltip).toHaveTextContent(/extremely long tooltip text/);
|
|
945
|
-
},
|
|
946
|
-
{ timeout: 2000 },
|
|
947
|
-
);
|
|
948
|
-
|
|
949
|
-
await userEvent.unhover(longTextButton);
|
|
950
|
-
});
|
|
951
|
-
|
|
952
|
-
await step('Special characters handling', async () => {
|
|
953
|
-
const specialButton = canvas.getByTestId('special-chars');
|
|
954
|
-
await userEvent.hover(specialButton);
|
|
955
|
-
|
|
956
|
-
await waitFor(
|
|
957
|
-
async () => {
|
|
958
|
-
const tooltip = await findTooltipByContent();
|
|
959
|
-
await expect(tooltip).toBeInTheDocument();
|
|
960
|
-
await expect(tooltip).toHaveTextContent(/Special chars:/);
|
|
961
|
-
},
|
|
962
|
-
{ timeout: 2000 },
|
|
963
|
-
);
|
|
964
|
-
|
|
965
|
-
await userEvent.unhover(specialButton);
|
|
966
|
-
});
|
|
967
|
-
|
|
968
|
-
await step('HTML content sanitization', async () => {
|
|
969
|
-
const htmlButton = canvas.getByTestId('html-content');
|
|
970
|
-
await userEvent.hover(htmlButton);
|
|
971
|
-
|
|
972
|
-
await waitFor(
|
|
973
|
-
async () => {
|
|
974
|
-
const tooltip = await findTooltipByContent();
|
|
975
|
-
await expect(tooltip).toBeInTheDocument();
|
|
976
|
-
// Should contain the text but not execute HTML/scripts
|
|
977
|
-
await expect(tooltip).toHaveTextContent(/HTML content test/);
|
|
978
|
-
},
|
|
979
|
-
{ timeout: 2000 },
|
|
980
|
-
);
|
|
981
|
-
|
|
982
|
-
await userEvent.unhover(htmlButton);
|
|
983
|
-
});
|
|
984
|
-
|
|
985
|
-
await step('Invalid props handling', async () => {
|
|
986
|
-
const invalidButton = canvas.getByTestId('invalid-props');
|
|
987
|
-
|
|
988
|
-
// Component should handle invalid props gracefully
|
|
989
|
-
await expect(invalidButton).toBeInTheDocument();
|
|
990
|
-
|
|
991
|
-
await userEvent.hover(invalidButton);
|
|
992
|
-
// Should not crash and either show nothing or handle gracefully
|
|
993
|
-
await new Promise((resolve) => window.setTimeout(resolve, 500));
|
|
994
|
-
await userEvent.unhover(invalidButton);
|
|
995
|
-
});
|
|
996
|
-
},
|
|
997
|
-
};
|
|
998
|
-
|
|
999
|
-
// 7.7 Integration Tests
|
|
1000
|
-
const IntegrationTestComponent = () => {
|
|
1001
|
-
const [count, setCount] = React.useState(0);
|
|
1002
|
-
const [showTooltips, setShowTooltips] = React.useState(true);
|
|
1003
|
-
|
|
1004
|
-
return (
|
|
1005
|
-
<Box sx={{ p: 4, display: 'flex', flexDirection: 'column', gap: 3, alignItems: 'center' }}>
|
|
1006
|
-
<Typography variant="h6" data-testid="counter-display">
|
|
1007
|
-
Count: {count}
|
|
1008
|
-
</Typography>
|
|
1009
|
-
|
|
1010
|
-
<Stack direction="row" spacing={2}>
|
|
1011
|
-
<Button
|
|
1012
|
-
variant="outlined"
|
|
1013
|
-
onClick={() => setShowTooltips(!showTooltips)}
|
|
1014
|
-
data-testid="toggle-tooltips"
|
|
1015
|
-
>
|
|
1016
|
-
Toggle Tooltips
|
|
1017
|
-
</Button>
|
|
1018
|
-
|
|
1019
|
-
<Button variant="outlined" onClick={() => setCount(0)} data-testid="reset-counter">
|
|
1020
|
-
Reset
|
|
1021
|
-
</Button>
|
|
1022
|
-
</Stack>
|
|
1023
|
-
|
|
1024
|
-
<Stack direction="row" spacing={2}>
|
|
1025
|
-
{showTooltips ? (
|
|
1026
|
-
<>
|
|
1027
|
-
<Tooltip title={`Increment counter (current: ${count})`} variant="default">
|
|
1028
|
-
<Button
|
|
1029
|
-
variant="contained"
|
|
1030
|
-
color="primary"
|
|
1031
|
-
onClick={() => setCount((c) => c + 1)}
|
|
1032
|
-
data-testid="increment-with-tooltip"
|
|
1033
|
-
>
|
|
1034
|
-
+
|
|
1035
|
-
</Button>
|
|
1036
|
-
</Tooltip>
|
|
1037
|
-
|
|
1038
|
-
<Tooltip title={`Decrement counter (current: ${count})`} variant="dark">
|
|
1039
|
-
<Button
|
|
1040
|
-
variant="contained"
|
|
1041
|
-
color="secondary"
|
|
1042
|
-
onClick={() => setCount((c) => c - 1)}
|
|
1043
|
-
data-testid="decrement-with-tooltip"
|
|
1044
|
-
>
|
|
1045
|
-
-
|
|
1046
|
-
</Button>
|
|
1047
|
-
</Tooltip>
|
|
1048
|
-
</>
|
|
1049
|
-
) : (
|
|
1050
|
-
<>
|
|
1051
|
-
<Button
|
|
1052
|
-
variant="contained"
|
|
1053
|
-
color="primary"
|
|
1054
|
-
onClick={() => setCount((c) => c + 1)}
|
|
1055
|
-
data-testid="increment-without-tooltip"
|
|
1056
|
-
>
|
|
1057
|
-
+
|
|
1058
|
-
</Button>
|
|
1059
|
-
|
|
1060
|
-
<Button
|
|
1061
|
-
variant="contained"
|
|
1062
|
-
color="secondary"
|
|
1063
|
-
onClick={() => setCount((c) => c - 1)}
|
|
1064
|
-
data-testid="decrement-without-tooltip"
|
|
1065
|
-
>
|
|
1066
|
-
-
|
|
1067
|
-
</Button>
|
|
1068
|
-
</>
|
|
1069
|
-
)}
|
|
1070
|
-
</Stack>
|
|
1071
|
-
</Box>
|
|
1072
|
-
);
|
|
1073
|
-
};
|
|
1074
|
-
|
|
1075
|
-
export const IntegrationTest: Story = {
|
|
1076
|
-
name: '🔗 Integration Test',
|
|
1077
|
-
render: () => <IntegrationTestComponent />,
|
|
1078
|
-
play: async ({ canvasElement, step }) => {
|
|
1079
|
-
const canvas = within(canvasElement);
|
|
1080
|
-
|
|
1081
|
-
await step('Integration with state management', async () => {
|
|
1082
|
-
const counterDisplay = canvas.getByTestId('counter-display');
|
|
1083
|
-
const incrementButton = canvas.getByTestId('increment-with-tooltip');
|
|
1084
|
-
|
|
1085
|
-
await expect(counterDisplay).toHaveTextContent('Count: 0');
|
|
1086
|
-
|
|
1087
|
-
// Click increment button
|
|
1088
|
-
await userEvent.click(incrementButton);
|
|
1089
|
-
|
|
1090
|
-
await waitFor(() => {
|
|
1091
|
-
expect(counterDisplay).toHaveTextContent('Count: 1');
|
|
1092
|
-
});
|
|
1093
|
-
});
|
|
1094
|
-
|
|
1095
|
-
await step('Tooltip content updates with state', async () => {
|
|
1096
|
-
const incrementButton = canvas.getByTestId('increment-with-tooltip');
|
|
1097
|
-
|
|
1098
|
-
// Hover to see tooltip with updated count
|
|
1099
|
-
await userEvent.hover(incrementButton);
|
|
1100
|
-
|
|
1101
|
-
await waitFor(
|
|
1102
|
-
async () => {
|
|
1103
|
-
const tooltip = await findTooltipByContent();
|
|
1104
|
-
await expect(tooltip).toHaveTextContent('current: 1');
|
|
1105
|
-
},
|
|
1106
|
-
{ timeout: 2000 },
|
|
1107
|
-
);
|
|
1108
|
-
|
|
1109
|
-
await userEvent.unhover(incrementButton);
|
|
1110
|
-
});
|
|
1111
|
-
|
|
1112
|
-
await step('Conditional tooltip rendering', async () => {
|
|
1113
|
-
const toggleButton = canvas.getByTestId('toggle-tooltips');
|
|
1114
|
-
|
|
1115
|
-
// Toggle tooltips off
|
|
1116
|
-
await userEvent.click(toggleButton);
|
|
1117
|
-
|
|
1118
|
-
// Verify buttons without tooltips exist
|
|
1119
|
-
await waitFor(() => {
|
|
1120
|
-
const incrementWithoutTooltip = canvas.getByTestId('increment-without-tooltip');
|
|
1121
|
-
expect(incrementWithoutTooltip).toBeInTheDocument();
|
|
1122
|
-
});
|
|
1123
|
-
});
|
|
1124
|
-
|
|
1125
|
-
await step('State reset integration', async () => {
|
|
1126
|
-
const resetButton = canvas.getByTestId('reset-counter');
|
|
1127
|
-
const counterDisplay = canvas.getByTestId('counter-display');
|
|
1128
|
-
|
|
1129
|
-
await userEvent.click(resetButton);
|
|
1130
|
-
|
|
1131
|
-
await waitFor(() => {
|
|
1132
|
-
expect(counterDisplay).toHaveTextContent('Count: 0');
|
|
1133
|
-
});
|
|
1134
|
-
|
|
1135
|
-
// Toggle tooltips back on
|
|
1136
|
-
const toggleButton = canvas.getByTestId('toggle-tooltips');
|
|
1137
|
-
await userEvent.click(toggleButton);
|
|
1138
|
-
|
|
1139
|
-
// Verify tooltip shows reset state
|
|
1140
|
-
const incrementButton = canvas.getByTestId('increment-with-tooltip');
|
|
1141
|
-
await userEvent.hover(incrementButton);
|
|
1142
|
-
|
|
1143
|
-
await waitFor(
|
|
1144
|
-
async () => {
|
|
1145
|
-
const tooltip = await findTooltipByContent();
|
|
1146
|
-
await expect(tooltip).toHaveTextContent('current: 0');
|
|
1147
|
-
},
|
|
1148
|
-
{ timeout: 2000 },
|
|
1149
|
-
);
|
|
1150
|
-
|
|
1151
|
-
await userEvent.unhover(incrementButton);
|
|
1152
|
-
});
|
|
1153
|
-
},
|
|
1154
|
-
};
|