@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,734 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import { expect, userEvent,waitFor, within } from 'storybook/test';
|
|
3
|
-
|
|
4
|
-
import { TimingDiagram } from './TimingDiagram';
|
|
5
|
-
|
|
6
|
-
const meta: Meta<typeof TimingDiagram> = {
|
|
7
|
-
title: 'Enhanced/TimingDiagram/Tests',
|
|
8
|
-
component: TimingDiagram,
|
|
9
|
-
parameters: {
|
|
10
|
-
layout: 'centered',
|
|
11
|
-
chromatic: { disableSnapshot: false },
|
|
12
|
-
},
|
|
13
|
-
tags: ['autodocs', 'test', 'component:TimingDiagram'],
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export default meta;
|
|
17
|
-
type Story = StoryObj<typeof meta>;
|
|
18
|
-
|
|
19
|
-
const sampleData = {
|
|
20
|
-
dns: 45,
|
|
21
|
-
connect: 120,
|
|
22
|
-
ssl: 180,
|
|
23
|
-
request: 25,
|
|
24
|
-
response: 380,
|
|
25
|
-
total: 750,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// Basic Interaction Test - Verify timing calculations and rendering
|
|
29
|
-
export const BasicInteraction: Story = {
|
|
30
|
-
args: {
|
|
31
|
-
data: sampleData,
|
|
32
|
-
variant: 'waterfall',
|
|
33
|
-
showLabels: true,
|
|
34
|
-
showTooltips: true,
|
|
35
|
-
animated: true,
|
|
36
|
-
},
|
|
37
|
-
play: async ({ canvasElement }) => {
|
|
38
|
-
const canvas = within(canvasElement);
|
|
39
|
-
|
|
40
|
-
// Verify the timing diagram renders
|
|
41
|
-
const container = canvas.getByRole('region', { name: /timing diagram/i });
|
|
42
|
-
await expect(container).toBeInTheDocument();
|
|
43
|
-
|
|
44
|
-
// Check that all timing segments are rendered
|
|
45
|
-
const segments = container.querySelectorAll('[data-testid^="timing-segment"]');
|
|
46
|
-
const expectedPhases = Object.entries(sampleData).filter(
|
|
47
|
-
([key, value]) => key !== 'total' && value > 0,
|
|
48
|
-
).length;
|
|
49
|
-
await expect(segments.length).toBe(expectedPhases);
|
|
50
|
-
|
|
51
|
-
// Verify DNS segment exists and has correct width percentage
|
|
52
|
-
const dnsSegment = container.querySelector('[data-testid="timing-segment-dns"]') as HTMLElement;
|
|
53
|
-
await expect(dnsSegment).toBeInTheDocument();
|
|
54
|
-
const dnsPercentage = (sampleData.dns / sampleData.total) * 100;
|
|
55
|
-
const dnsActualWidth = parseFloat(dnsSegment.style.width.replace('%', ''));
|
|
56
|
-
await expect(Math.abs(dnsActualWidth - dnsPercentage)).toBeLessThan(0.1);
|
|
57
|
-
|
|
58
|
-
// Verify connect segment width
|
|
59
|
-
const connectSegment = container.querySelector(
|
|
60
|
-
'[data-testid="timing-segment-connect"]',
|
|
61
|
-
) as HTMLElement;
|
|
62
|
-
await expect(connectSegment).toBeInTheDocument();
|
|
63
|
-
const connectPercentage = (sampleData.connect / sampleData.total) * 100;
|
|
64
|
-
const connectActualWidth = parseFloat(connectSegment.style.width.replace('%', ''));
|
|
65
|
-
await expect(Math.abs(connectActualWidth - connectPercentage)).toBeLessThan(0.1);
|
|
66
|
-
|
|
67
|
-
// Verify response segment width
|
|
68
|
-
const responseSegment = container.querySelector(
|
|
69
|
-
'[data-testid="timing-segment-response"]',
|
|
70
|
-
) as HTMLElement;
|
|
71
|
-
await expect(responseSegment).toBeInTheDocument();
|
|
72
|
-
const responsePercentage = (sampleData.response / sampleData.total) * 100;
|
|
73
|
-
const responseActualWidth = parseFloat(responseSegment.style.width.replace('%', ''));
|
|
74
|
-
await expect(Math.abs(responseActualWidth - responsePercentage)).toBeLessThan(0.1);
|
|
75
|
-
|
|
76
|
-
// Check timeline markers are rendered with correct values
|
|
77
|
-
const timeLabels = container.querySelectorAll('.MuiTypography-root');
|
|
78
|
-
const totalTimeLabel = Array.from(timeLabels).find((el) => el.textContent?.includes('750ms'));
|
|
79
|
-
await expect(totalTimeLabel).toBeInTheDocument();
|
|
80
|
-
|
|
81
|
-
// Verify labels show correct timing values for segments >10% width
|
|
82
|
-
const labels = container.querySelectorAll('[data-testid="timing-label"]');
|
|
83
|
-
await expect(labels.length).toBeGreaterThan(0);
|
|
84
|
-
// DNS (6%) won't show label, check connect and response which are >10%
|
|
85
|
-
const connectLabel = Array.from(labels).find((el) => el.textContent === '120ms');
|
|
86
|
-
await expect(connectLabel).toBeInTheDocument();
|
|
87
|
-
const responseLabel = Array.from(labels).find((el) => el.textContent === '380ms');
|
|
88
|
-
await expect(responseLabel).toBeInTheDocument();
|
|
89
|
-
|
|
90
|
-
await waitFor(() => {
|
|
91
|
-
const status = document.createElement('div');
|
|
92
|
-
status.setAttribute('aria-label', 'Status of the test run');
|
|
93
|
-
status.textContent = 'PASS';
|
|
94
|
-
canvasElement.appendChild(status);
|
|
95
|
-
});
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
// State Change Test - Verify stacked variant calculations
|
|
100
|
-
export const StateChangeTest: Story = {
|
|
101
|
-
args: {
|
|
102
|
-
data: sampleData,
|
|
103
|
-
variant: 'stacked',
|
|
104
|
-
showLabels: true,
|
|
105
|
-
showTooltips: true,
|
|
106
|
-
animated: true,
|
|
107
|
-
},
|
|
108
|
-
play: async ({ canvasElement }) => {
|
|
109
|
-
const canvas = within(canvasElement);
|
|
110
|
-
|
|
111
|
-
// Verify initial state
|
|
112
|
-
const container = canvas.getByRole('region', { name: /timing diagram/i });
|
|
113
|
-
await expect(container).toBeInTheDocument();
|
|
114
|
-
|
|
115
|
-
// Check variant is applied
|
|
116
|
-
const stackedContainer = container.querySelector('[data-variant="stacked"]');
|
|
117
|
-
await expect(stackedContainer).toBeInTheDocument();
|
|
118
|
-
|
|
119
|
-
// Verify segments are stacked horizontally with correct widths
|
|
120
|
-
const totalWidth = 100;
|
|
121
|
-
let calculatedTotal = 0;
|
|
122
|
-
|
|
123
|
-
// Check each segment's width percentage - check all segments
|
|
124
|
-
const allSegments = container.querySelectorAll('[data-testid^="timing-segment-"]');
|
|
125
|
-
for (const segment of allSegments) {
|
|
126
|
-
const segmentElement = segment as HTMLElement;
|
|
127
|
-
const actualWidth = parseFloat(segmentElement.style.width?.replace('%', '') || '0');
|
|
128
|
-
calculatedTotal += actualWidth;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Verify total width adds up to 100%
|
|
132
|
-
await expect(Math.abs(calculatedTotal - totalWidth)).toBeLessThan(5);
|
|
133
|
-
|
|
134
|
-
// Check total time display
|
|
135
|
-
const totalTimeText =
|
|
136
|
-
container.querySelector('text')?.textContent ||
|
|
137
|
-
Array.from(container.querySelectorAll('.MuiTypography-caption')).find((el) =>
|
|
138
|
-
el.textContent?.includes('Total:'),
|
|
139
|
-
)?.textContent;
|
|
140
|
-
await expect(totalTimeText).toContain('750ms');
|
|
141
|
-
|
|
142
|
-
await waitFor(() => {
|
|
143
|
-
const status = document.createElement('div');
|
|
144
|
-
status.setAttribute('aria-label', 'Status of the test run');
|
|
145
|
-
status.textContent = 'PASS';
|
|
146
|
-
canvasElement.appendChild(status);
|
|
147
|
-
});
|
|
148
|
-
},
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
// Visual States Test - Verify horizontal variant and timing values
|
|
152
|
-
export const VisualStatesTest: Story = {
|
|
153
|
-
args: {
|
|
154
|
-
data: sampleData,
|
|
155
|
-
variant: 'horizontal',
|
|
156
|
-
showLabels: true,
|
|
157
|
-
showTooltips: false,
|
|
158
|
-
animated: false,
|
|
159
|
-
},
|
|
160
|
-
play: async ({ canvasElement }) => {
|
|
161
|
-
const canvas = within(canvasElement);
|
|
162
|
-
|
|
163
|
-
// Verify the component renders
|
|
164
|
-
const container = canvas.getByRole('region', { name: /timing diagram/i });
|
|
165
|
-
await expect(container).toBeInTheDocument();
|
|
166
|
-
|
|
167
|
-
// Check that animations are disabled
|
|
168
|
-
const animatedElements = container.querySelectorAll('[data-animated="false"]');
|
|
169
|
-
await expect(animatedElements.length).toBeGreaterThan(0);
|
|
170
|
-
|
|
171
|
-
// Verify horizontal variant structure
|
|
172
|
-
const horizontalContainer = container.querySelector('[data-variant="horizontal"]');
|
|
173
|
-
await expect(horizontalContainer).toBeInTheDocument();
|
|
174
|
-
|
|
175
|
-
// Check each phase has label, bar, and value
|
|
176
|
-
const segments = container.querySelectorAll('[data-testid^="timing-segment"]');
|
|
177
|
-
|
|
178
|
-
for (const segment of segments) {
|
|
179
|
-
// Each segment should have a label
|
|
180
|
-
const label = segment.querySelector('.label');
|
|
181
|
-
await expect(label).toBeInTheDocument();
|
|
182
|
-
|
|
183
|
-
// Each segment should have a bar
|
|
184
|
-
const bar = segment.querySelector('.bar');
|
|
185
|
-
await expect(bar).toBeInTheDocument();
|
|
186
|
-
|
|
187
|
-
// Each segment should have a value
|
|
188
|
-
const value = segment.querySelector('.value');
|
|
189
|
-
await expect(value).toBeInTheDocument();
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Verify specific timing values are displayed
|
|
193
|
-
const timingLabels = container.querySelectorAll('[data-testid="timing-label"]');
|
|
194
|
-
const timingValues = Array.from(timingLabels).map((el) => el.textContent);
|
|
195
|
-
|
|
196
|
-
// Check DNS timing
|
|
197
|
-
await expect(timingValues).toContain('45ms');
|
|
198
|
-
// Check connect timing
|
|
199
|
-
await expect(timingValues).toContain('120ms');
|
|
200
|
-
// Check SSL timing
|
|
201
|
-
await expect(timingValues).toContain('180ms');
|
|
202
|
-
// Check request timing
|
|
203
|
-
await expect(timingValues).toContain('25ms');
|
|
204
|
-
// Check response timing
|
|
205
|
-
await expect(timingValues).toContain('380ms');
|
|
206
|
-
|
|
207
|
-
// Verify total time display
|
|
208
|
-
const totalTimeElement = Array.from(container.querySelectorAll('.MuiTypography-body2')).find(
|
|
209
|
-
(el) => el.textContent?.includes('Total Time:'),
|
|
210
|
-
);
|
|
211
|
-
await expect(totalTimeElement?.textContent).toContain('750ms');
|
|
212
|
-
|
|
213
|
-
await waitFor(() => {
|
|
214
|
-
const status = document.createElement('div');
|
|
215
|
-
status.setAttribute('aria-label', 'Status of the test run');
|
|
216
|
-
status.textContent = 'PASS';
|
|
217
|
-
canvasElement.appendChild(status);
|
|
218
|
-
});
|
|
219
|
-
},
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
// Responsive Design Test
|
|
223
|
-
export const ResponsiveDesignTest: Story = {
|
|
224
|
-
args: {
|
|
225
|
-
data: sampleData,
|
|
226
|
-
variant: 'waterfall',
|
|
227
|
-
showLabels: true,
|
|
228
|
-
showTooltips: true,
|
|
229
|
-
animated: true,
|
|
230
|
-
},
|
|
231
|
-
parameters: {
|
|
232
|
-
viewport: {
|
|
233
|
-
defaultViewport: 'mobile1',
|
|
234
|
-
},
|
|
235
|
-
},
|
|
236
|
-
play: async ({ canvasElement }) => {
|
|
237
|
-
const canvas = within(canvasElement);
|
|
238
|
-
|
|
239
|
-
// Verify responsive rendering
|
|
240
|
-
const container = canvas.getByRole('region', { name: /timing diagram/i });
|
|
241
|
-
await expect(container).toBeInTheDocument();
|
|
242
|
-
|
|
243
|
-
// Check that it adapts to viewport
|
|
244
|
-
const computedStyle = window.getComputedStyle(container);
|
|
245
|
-
await expect(computedStyle.width).toBeDefined();
|
|
246
|
-
|
|
247
|
-
await waitFor(() => {
|
|
248
|
-
const status = document.createElement('div');
|
|
249
|
-
status.setAttribute('aria-label', 'Status of the test run');
|
|
250
|
-
status.textContent = 'PASS';
|
|
251
|
-
canvasElement.appendChild(status);
|
|
252
|
-
});
|
|
253
|
-
},
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
// Performance Test - Verify large values formatting and scaling
|
|
257
|
-
export const PerformanceTest: Story = {
|
|
258
|
-
args: {
|
|
259
|
-
data: {
|
|
260
|
-
dns: 150,
|
|
261
|
-
connect: 400,
|
|
262
|
-
ssl: 600,
|
|
263
|
-
request: 80,
|
|
264
|
-
response: 1200,
|
|
265
|
-
total: 2430,
|
|
266
|
-
},
|
|
267
|
-
variant: 'stacked',
|
|
268
|
-
showLabels: true,
|
|
269
|
-
showTooltips: true,
|
|
270
|
-
animated: true,
|
|
271
|
-
},
|
|
272
|
-
play: async ({ canvasElement }) => {
|
|
273
|
-
const startTime = Date.now();
|
|
274
|
-
const canvas = within(canvasElement);
|
|
275
|
-
|
|
276
|
-
// Verify rendering with large data
|
|
277
|
-
const container = canvas.getByRole('region', { name: /timing diagram/i });
|
|
278
|
-
await expect(container).toBeInTheDocument();
|
|
279
|
-
|
|
280
|
-
const renderTime = Date.now() - startTime;
|
|
281
|
-
// Should render within reasonable time
|
|
282
|
-
await expect(renderTime).toBeLessThan(1000);
|
|
283
|
-
|
|
284
|
-
// Verify large values are formatted correctly (seconds instead of ms)
|
|
285
|
-
const totalTimeDisplay = Array.from(container.querySelectorAll('.MuiTypography-caption')).find(
|
|
286
|
-
(el) => el.textContent?.includes('Total:'),
|
|
287
|
-
);
|
|
288
|
-
await expect(totalTimeDisplay?.textContent).toContain('2.43s');
|
|
289
|
-
|
|
290
|
-
// Verify response segment (largest) has correct proportion
|
|
291
|
-
const responseSegment = container.querySelector(
|
|
292
|
-
'[data-testid="timing-segment-response"]',
|
|
293
|
-
) as HTMLElement;
|
|
294
|
-
const responseExpectedWidth = (1200 / 2430) * 100; // ~49.4%
|
|
295
|
-
const responseActualWidth = parseFloat(responseSegment?.style.width || '0');
|
|
296
|
-
await expect(Math.abs(responseActualWidth - responseExpectedWidth)).toBeLessThan(0.5);
|
|
297
|
-
|
|
298
|
-
// Verify SSL segment proportion
|
|
299
|
-
const sslSegment = container.querySelector('[data-testid="timing-segment-ssl"]') as HTMLElement;
|
|
300
|
-
const sslExpectedWidth = (600 / 2430) * 100; // ~24.7%
|
|
301
|
-
const sslActualWidth = parseFloat(sslSegment?.style.width || '0');
|
|
302
|
-
await expect(Math.abs(sslActualWidth - sslExpectedWidth)).toBeLessThan(0.5);
|
|
303
|
-
|
|
304
|
-
// Check that labels show correct formatted values
|
|
305
|
-
const labels = container.querySelectorAll('[data-testid="timing-label"]');
|
|
306
|
-
const labelTexts = Array.from(labels).map((el) => el.textContent);
|
|
307
|
-
|
|
308
|
-
// Values over 1000ms should be in seconds
|
|
309
|
-
await expect(labelTexts.some((text) => text === '1.20s')).toBe(true); // response
|
|
310
|
-
// Only segments >10% show labels in stacked variant
|
|
311
|
-
await expect(labelTexts.some((text) => text === '400ms')).toBe(true); // connect (16.46%)
|
|
312
|
-
await expect(labelTexts.some((text) => text === '600ms')).toBe(true); // ssl (24.69%)
|
|
313
|
-
// DNS (6.17%) and request (3.29%) won't show labels due to <10% threshold
|
|
314
|
-
|
|
315
|
-
await waitFor(() => {
|
|
316
|
-
const status = document.createElement('div');
|
|
317
|
-
status.setAttribute('aria-label', 'Status of the test run');
|
|
318
|
-
status.textContent = 'PASS';
|
|
319
|
-
canvasElement.appendChild(status);
|
|
320
|
-
});
|
|
321
|
-
},
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
// Edge Cases Test - Verify handling of partial data and zero values
|
|
325
|
-
export const EdgeCasesTest: Story = {
|
|
326
|
-
args: {
|
|
327
|
-
data: {
|
|
328
|
-
dns: 0, // Zero value should be filtered out
|
|
329
|
-
request: 50,
|
|
330
|
-
response: 150,
|
|
331
|
-
total: 200,
|
|
332
|
-
},
|
|
333
|
-
variant: 'waterfall',
|
|
334
|
-
showLabels: true,
|
|
335
|
-
showTooltips: true,
|
|
336
|
-
animated: true,
|
|
337
|
-
},
|
|
338
|
-
play: async ({ canvasElement }) => {
|
|
339
|
-
const canvas = within(canvasElement);
|
|
340
|
-
|
|
341
|
-
// Verify handling of minimal data
|
|
342
|
-
const container = canvas.getByRole('region', { name: /timing diagram/i });
|
|
343
|
-
await expect(container).toBeInTheDocument();
|
|
344
|
-
|
|
345
|
-
// Should handle missing phases gracefully - only non-zero phases rendered
|
|
346
|
-
const segments = container.querySelectorAll('[data-testid^="timing-segment"]');
|
|
347
|
-
await expect(segments.length).toBe(2); // Only request and response
|
|
348
|
-
|
|
349
|
-
// DNS segment should not exist (zero value)
|
|
350
|
-
const dnsSegment = container.querySelector('[data-testid="timing-segment-dns"]');
|
|
351
|
-
await expect(dnsSegment).not.toBeInTheDocument();
|
|
352
|
-
|
|
353
|
-
// Connect segment should not exist (undefined)
|
|
354
|
-
const connectSegment = container.querySelector('[data-testid="timing-segment-connect"]');
|
|
355
|
-
await expect(connectSegment).not.toBeInTheDocument();
|
|
356
|
-
|
|
357
|
-
// Request segment should exist with correct width
|
|
358
|
-
const requestSegment = container.querySelector(
|
|
359
|
-
'[data-testid="timing-segment-request"]',
|
|
360
|
-
) as HTMLElement;
|
|
361
|
-
await expect(requestSegment).toBeInTheDocument();
|
|
362
|
-
const requestExpectedWidth = (50 / 200) * 100; // 25%
|
|
363
|
-
await expect(requestSegment.style.width).toBe(`${requestExpectedWidth}%`);
|
|
364
|
-
|
|
365
|
-
// Response segment should exist with correct width
|
|
366
|
-
const responseSegment = container.querySelector(
|
|
367
|
-
'[data-testid="timing-segment-response"]',
|
|
368
|
-
) as HTMLElement;
|
|
369
|
-
await expect(responseSegment).toBeInTheDocument();
|
|
370
|
-
const responseExpectedWidth = (150 / 200) * 100; // 75%
|
|
371
|
-
await expect(responseSegment.style.width).toBe(`${responseExpectedWidth}%`);
|
|
372
|
-
|
|
373
|
-
// Check waterfall offset positioning
|
|
374
|
-
const requestOffset = parseFloat(requestSegment.style.left || '0');
|
|
375
|
-
await expect(requestOffset).toBe(0); // First segment starts at 0
|
|
376
|
-
|
|
377
|
-
const responseOffset = parseFloat(responseSegment.style.left || '0');
|
|
378
|
-
await expect(responseOffset).toBe(requestExpectedWidth); // Second segment starts after first
|
|
379
|
-
|
|
380
|
-
// Verify timeline markers
|
|
381
|
-
const timeLabels = container.querySelectorAll('.MuiTypography-root');
|
|
382
|
-
const timeMarkers = Array.from(timeLabels)
|
|
383
|
-
.filter((el) => el.textContent?.includes('ms'))
|
|
384
|
-
.map((el) => el.textContent);
|
|
385
|
-
|
|
386
|
-
await expect(timeMarkers).toContain('0ms');
|
|
387
|
-
await expect(timeMarkers).toContain('100ms'); // Half of 200ms
|
|
388
|
-
await expect(timeMarkers).toContain('200ms'); // Total
|
|
389
|
-
|
|
390
|
-
await waitFor(() => {
|
|
391
|
-
const status = document.createElement('div');
|
|
392
|
-
status.setAttribute('aria-label', 'Status of the test run');
|
|
393
|
-
status.textContent = 'PASS';
|
|
394
|
-
canvasElement.appendChild(status);
|
|
395
|
-
});
|
|
396
|
-
},
|
|
397
|
-
};
|
|
398
|
-
|
|
399
|
-
// Accessibility Test - Verify ARIA attributes and semantic structure
|
|
400
|
-
export const AccessibilityTest: Story = {
|
|
401
|
-
args: {
|
|
402
|
-
data: sampleData,
|
|
403
|
-
variant: 'waterfall',
|
|
404
|
-
showLabels: true,
|
|
405
|
-
showTooltips: true,
|
|
406
|
-
animated: true,
|
|
407
|
-
},
|
|
408
|
-
play: async ({ canvasElement }) => {
|
|
409
|
-
const canvas = within(canvasElement);
|
|
410
|
-
|
|
411
|
-
// Check for proper ARIA attributes
|
|
412
|
-
const container = canvas.getByRole('region', { name: /timing diagram/i });
|
|
413
|
-
await expect(container).toBeInTheDocument();
|
|
414
|
-
await expect(container).toHaveAttribute('aria-label', 'Timing diagram');
|
|
415
|
-
|
|
416
|
-
// Check heading structure
|
|
417
|
-
const heading = canvas.getByText('Request Timing');
|
|
418
|
-
await expect(heading).toBeInTheDocument();
|
|
419
|
-
await expect(heading.tagName).toBe('H6');
|
|
420
|
-
|
|
421
|
-
// Verify segments are accessible
|
|
422
|
-
const segments = container.querySelectorAll('[data-testid^="timing-segment"]');
|
|
423
|
-
for (const segment of segments) {
|
|
424
|
-
// Each segment should have describedby for tooltip
|
|
425
|
-
const hasTooltip = segment.closest('[aria-describedby]');
|
|
426
|
-
if (hasTooltip) {
|
|
427
|
-
await expect(hasTooltip).toHaveAttribute('aria-describedby');
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// Check legend is present and accessible
|
|
432
|
-
const legendItems = container.querySelectorAll('.MuiTypography-root');
|
|
433
|
-
const hasLegendLabels = Array.from(legendItems).some(
|
|
434
|
-
(el) =>
|
|
435
|
-
el.textContent?.includes('DNS Lookup') ||
|
|
436
|
-
el.textContent?.includes('Connection') ||
|
|
437
|
-
el.textContent?.includes('SSL/TLS'),
|
|
438
|
-
);
|
|
439
|
-
await expect(hasLegendLabels).toBe(true);
|
|
440
|
-
|
|
441
|
-
await waitFor(() => {
|
|
442
|
-
const status = document.createElement('div');
|
|
443
|
-
status.setAttribute('aria-label', 'Status of the test run');
|
|
444
|
-
status.textContent = 'PASS';
|
|
445
|
-
canvasElement.appendChild(status);
|
|
446
|
-
});
|
|
447
|
-
},
|
|
448
|
-
};
|
|
449
|
-
|
|
450
|
-
// Keyboard Navigation Test - Verify keyboard interactions
|
|
451
|
-
export const KeyboardNavigationTest: Story = {
|
|
452
|
-
args: {
|
|
453
|
-
data: sampleData,
|
|
454
|
-
variant: 'horizontal',
|
|
455
|
-
showLabels: true,
|
|
456
|
-
showTooltips: true,
|
|
457
|
-
animated: false,
|
|
458
|
-
},
|
|
459
|
-
play: async ({ canvasElement }) => {
|
|
460
|
-
const canvas = within(canvasElement);
|
|
461
|
-
|
|
462
|
-
const container = canvas.getByRole('region', { name: /timing diagram/i });
|
|
463
|
-
await expect(container).toBeInTheDocument();
|
|
464
|
-
|
|
465
|
-
// Focus on the container
|
|
466
|
-
container.focus();
|
|
467
|
-
await waitFor(() => expect(document.activeElement).toBe(container));
|
|
468
|
-
|
|
469
|
-
// Tab through interactive elements
|
|
470
|
-
await userEvent.tab();
|
|
471
|
-
|
|
472
|
-
// Check tooltips can be triggered via keyboard
|
|
473
|
-
const segments = container.querySelectorAll('[data-testid^="timing-segment"]');
|
|
474
|
-
if (segments.length > 0) {
|
|
475
|
-
const firstSegment = segments[0] as HTMLElement;
|
|
476
|
-
|
|
477
|
-
// Simulate keyboard focus
|
|
478
|
-
firstSegment.focus?.();
|
|
479
|
-
|
|
480
|
-
// Verify segment can receive focus for tooltip
|
|
481
|
-
const hasAriaDescribedBy = firstSegment.closest('[aria-describedby]');
|
|
482
|
-
await expect(hasAriaDescribedBy || firstSegment).toBeTruthy();
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
await waitFor(() => {
|
|
486
|
-
const status = document.createElement('div');
|
|
487
|
-
status.setAttribute('aria-label', 'Status of the test run');
|
|
488
|
-
status.textContent = 'PASS';
|
|
489
|
-
canvasElement.appendChild(status);
|
|
490
|
-
});
|
|
491
|
-
},
|
|
492
|
-
};
|
|
493
|
-
|
|
494
|
-
// Screen Reader Test - Verify screen reader compatibility
|
|
495
|
-
export const ScreenReaderTest: Story = {
|
|
496
|
-
args: {
|
|
497
|
-
data: sampleData,
|
|
498
|
-
variant: 'stacked',
|
|
499
|
-
showLabels: true,
|
|
500
|
-
showTooltips: true,
|
|
501
|
-
animated: false,
|
|
502
|
-
},
|
|
503
|
-
play: async ({ canvasElement }) => {
|
|
504
|
-
const canvas = within(canvasElement);
|
|
505
|
-
|
|
506
|
-
const container = canvas.getByRole('region', { name: /timing diagram/i });
|
|
507
|
-
await expect(container).toBeInTheDocument();
|
|
508
|
-
|
|
509
|
-
// Check that timing values are available to screen readers
|
|
510
|
-
const timingLabels = container.querySelectorAll('[data-testid="timing-label"]');
|
|
511
|
-
for (const label of timingLabels) {
|
|
512
|
-
const text = label.textContent;
|
|
513
|
-
await expect(text).toBeTruthy();
|
|
514
|
-
// Verify format is readable (e.g., "45ms" or "1.20s")
|
|
515
|
-
await expect(text).toMatch(/^\d+(\.\d+)?(ms|s)$/);
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
// Check total time is announced
|
|
519
|
-
const totalTimeElements = container.querySelectorAll(
|
|
520
|
-
'.MuiTypography-caption, .MuiTypography-body2',
|
|
521
|
-
);
|
|
522
|
-
const totalTimeElement = Array.from(totalTimeElements).find((el) =>
|
|
523
|
-
el.textContent?.includes('Total'),
|
|
524
|
-
);
|
|
525
|
-
await expect(totalTimeElement).toBeInTheDocument();
|
|
526
|
-
await expect(totalTimeElement?.textContent).toContain('750ms');
|
|
527
|
-
|
|
528
|
-
// Verify legend items are readable
|
|
529
|
-
const legendContainer = Array.from(container.querySelectorAll('.MuiBox-root')).find((el) =>
|
|
530
|
-
el.querySelector('.color'),
|
|
531
|
-
);
|
|
532
|
-
if (legendContainer) {
|
|
533
|
-
const legendLabels = legendContainer.querySelectorAll('.label');
|
|
534
|
-
await expect(legendLabels.length).toBeGreaterThan(0);
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
await waitFor(() => {
|
|
538
|
-
const status = document.createElement('div');
|
|
539
|
-
status.setAttribute('aria-label', 'Status of the test run');
|
|
540
|
-
status.textContent = 'PASS';
|
|
541
|
-
canvasElement.appendChild(status);
|
|
542
|
-
});
|
|
543
|
-
},
|
|
544
|
-
};
|
|
545
|
-
|
|
546
|
-
// Focus Management Test - Verify focus states and management
|
|
547
|
-
export const FocusManagementTest: Story = {
|
|
548
|
-
args: {
|
|
549
|
-
data: sampleData,
|
|
550
|
-
variant: 'waterfall',
|
|
551
|
-
showLabels: true,
|
|
552
|
-
showTooltips: true,
|
|
553
|
-
animated: true,
|
|
554
|
-
},
|
|
555
|
-
play: async ({ canvasElement }) => {
|
|
556
|
-
const canvas = within(canvasElement);
|
|
557
|
-
|
|
558
|
-
const container = canvas.getByRole('region', { name: /timing diagram/i });
|
|
559
|
-
await expect(container).toBeInTheDocument();
|
|
560
|
-
|
|
561
|
-
// Check container can receive focus
|
|
562
|
-
container.focus();
|
|
563
|
-
await waitFor(() => expect(document.activeElement).toBe(container));
|
|
564
|
-
|
|
565
|
-
// Verify segments have hover states (visual feedback)
|
|
566
|
-
const segments = container.querySelectorAll('[data-testid^="timing-segment"]');
|
|
567
|
-
for (const segment of segments) {
|
|
568
|
-
const computedStyle = window.getComputedStyle(segment);
|
|
569
|
-
|
|
570
|
-
// Segments should have transition for hover effect
|
|
571
|
-
await expect(computedStyle.transition).toContain('0.5s');
|
|
572
|
-
|
|
573
|
-
// Hover should change transform or shadow
|
|
574
|
-
await userEvent.hover(segment);
|
|
575
|
-
await waitFor(() => {
|
|
576
|
-
const hoverStyle = window.getComputedStyle(segment);
|
|
577
|
-
// Check for hover effect (transform or shadow change)
|
|
578
|
-
const hasHoverEffect = hoverStyle.transform !== 'none' || hoverStyle.boxShadow !== 'none';
|
|
579
|
-
expect(hasHoverEffect).toBe(true);
|
|
580
|
-
});
|
|
581
|
-
await userEvent.unhover(segment);
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
await waitFor(() => {
|
|
585
|
-
const status = document.createElement('div');
|
|
586
|
-
status.setAttribute('aria-label', 'Status of the test run');
|
|
587
|
-
status.textContent = 'PASS';
|
|
588
|
-
canvasElement.appendChild(status);
|
|
589
|
-
});
|
|
590
|
-
},
|
|
591
|
-
};
|
|
592
|
-
|
|
593
|
-
// Theme Variations Test - Verify interactive features and tooltips
|
|
594
|
-
export const ThemeVariationsTest: Story = {
|
|
595
|
-
args: {
|
|
596
|
-
data: sampleData,
|
|
597
|
-
variant: 'stacked',
|
|
598
|
-
showLabels: true,
|
|
599
|
-
showTooltips: true,
|
|
600
|
-
animated: true,
|
|
601
|
-
},
|
|
602
|
-
parameters: {
|
|
603
|
-
theme: 'dark',
|
|
604
|
-
},
|
|
605
|
-
play: async ({ canvasElement }) => {
|
|
606
|
-
const canvas = within(canvasElement);
|
|
607
|
-
|
|
608
|
-
// Verify theme support
|
|
609
|
-
const container = canvas.getByRole('region', { name: /timing diagram/i });
|
|
610
|
-
await expect(container).toBeInTheDocument();
|
|
611
|
-
|
|
612
|
-
// Check that segments have correct colors from phaseColors
|
|
613
|
-
const dnsSegment = container.querySelector('[data-testid="timing-segment-dns"]') as HTMLElement;
|
|
614
|
-
const dnsStyle = window.getComputedStyle(dnsSegment);
|
|
615
|
-
await expect(dnsStyle.background).toContain('rgb(156, 39, 176)'); // #9C27B0 in RGB
|
|
616
|
-
|
|
617
|
-
const connectSegment = container.querySelector(
|
|
618
|
-
'[data-testid="timing-segment-connect"]',
|
|
619
|
-
) as HTMLElement;
|
|
620
|
-
const connectStyle = window.getComputedStyle(connectSegment);
|
|
621
|
-
await expect(connectStyle.background).toContain('rgb(33, 150, 243)'); // #2196F3 in RGB
|
|
622
|
-
|
|
623
|
-
const sslSegment = container.querySelector('[data-testid="timing-segment-ssl"]') as HTMLElement;
|
|
624
|
-
const sslStyle = window.getComputedStyle(sslSegment);
|
|
625
|
-
await expect(sslStyle.background).toContain('rgb(0, 188, 212)'); // #00BCD4 in RGB
|
|
626
|
-
|
|
627
|
-
const requestSegment = container.querySelector(
|
|
628
|
-
'[data-testid="timing-segment-request"]',
|
|
629
|
-
) as HTMLElement;
|
|
630
|
-
const requestStyle = window.getComputedStyle(requestSegment);
|
|
631
|
-
await expect(requestStyle.background).toContain('rgb(76, 175, 80)'); // #4CAF50 in RGB
|
|
632
|
-
|
|
633
|
-
const responseSegment = container.querySelector(
|
|
634
|
-
'[data-testid="timing-segment-response"]',
|
|
635
|
-
) as HTMLElement;
|
|
636
|
-
const responseStyle = window.getComputedStyle(responseSegment);
|
|
637
|
-
await expect(responseStyle.background).toContain('rgb(255, 152, 0)'); // #FF9800 in RGB
|
|
638
|
-
|
|
639
|
-
// Verify component renders properly in theme
|
|
640
|
-
await expect(container).toHaveAttribute('role', 'region');
|
|
641
|
-
|
|
642
|
-
await waitFor(() => {
|
|
643
|
-
const status = document.createElement('div');
|
|
644
|
-
status.setAttribute('aria-label', 'Status of the test run');
|
|
645
|
-
status.textContent = 'PASS';
|
|
646
|
-
canvasElement.appendChild(status);
|
|
647
|
-
});
|
|
648
|
-
},
|
|
649
|
-
};
|
|
650
|
-
|
|
651
|
-
// Integration Test - Verify waterfall cascading and offsets
|
|
652
|
-
export const IntegrationTest: Story = {
|
|
653
|
-
args: {
|
|
654
|
-
data: sampleData,
|
|
655
|
-
variant: 'waterfall',
|
|
656
|
-
showLabels: true,
|
|
657
|
-
showTooltips: true,
|
|
658
|
-
animated: true,
|
|
659
|
-
height: 60,
|
|
660
|
-
},
|
|
661
|
-
play: async ({ canvasElement }) => {
|
|
662
|
-
const canvas = within(canvasElement);
|
|
663
|
-
|
|
664
|
-
// Verify full integration
|
|
665
|
-
const container = canvas.getByRole('region', { name: /timing diagram/i });
|
|
666
|
-
await expect(container).toBeInTheDocument();
|
|
667
|
-
|
|
668
|
-
// Check height prop affects waterfall container
|
|
669
|
-
const waterfallContainer = container.querySelector('[data-variant="waterfall"]') as HTMLElement;
|
|
670
|
-
await expect(waterfallContainer).toBeInTheDocument();
|
|
671
|
-
const containerHeight = parseInt(waterfallContainer.style.height || '0');
|
|
672
|
-
await expect(containerHeight).toBe(100); // height (60) + 40
|
|
673
|
-
|
|
674
|
-
// Verify waterfall cascading effect - each segment has different top position
|
|
675
|
-
const segments = container.querySelectorAll('[data-testid^="timing-segment"]');
|
|
676
|
-
const topPositions: number[] = [];
|
|
677
|
-
|
|
678
|
-
for (let i = 0; i < segments.length; i++) {
|
|
679
|
-
const segment = segments[i] as HTMLElement;
|
|
680
|
-
const topPos = parseInt(segment.style.top || '0');
|
|
681
|
-
topPositions.push(topPos);
|
|
682
|
-
|
|
683
|
-
// Each segment should be 8px lower than the previous
|
|
684
|
-
await expect(topPos).toBe(i * 8);
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
// Verify cumulative offset positioning
|
|
688
|
-
let cumulativeOffset = 0;
|
|
689
|
-
const dnsSegment = container.querySelector('[data-testid="timing-segment-dns"]') as HTMLElement;
|
|
690
|
-
if (dnsSegment) {
|
|
691
|
-
const dnsOffset = parseFloat(dnsSegment.style.left || '0');
|
|
692
|
-
await expect(dnsOffset).toBe(0); // First segment starts at 0
|
|
693
|
-
cumulativeOffset += parseFloat(dnsSegment.style.width || '0');
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
const connectSegment = container.querySelector(
|
|
697
|
-
'[data-testid="timing-segment-connect"]',
|
|
698
|
-
) as HTMLElement;
|
|
699
|
-
if (connectSegment) {
|
|
700
|
-
const connectOffset = parseFloat(connectSegment.style.left || '0');
|
|
701
|
-
await expect(Math.abs(connectOffset - cumulativeOffset)).toBeLessThan(0.1);
|
|
702
|
-
cumulativeOffset += parseFloat(connectSegment.style.width || '0');
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
const sslSegment = container.querySelector('[data-testid="timing-segment-ssl"]') as HTMLElement;
|
|
706
|
-
if (sslSegment) {
|
|
707
|
-
const sslOffset = parseFloat(sslSegment.style.left || '0');
|
|
708
|
-
await expect(Math.abs(sslOffset - cumulativeOffset)).toBeLessThan(0.1);
|
|
709
|
-
cumulativeOffset += parseFloat(sslSegment.style.width || '0');
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
// Verify legend is displayed with all phases
|
|
713
|
-
const legendItems = container.querySelectorAll('.MuiBox-root');
|
|
714
|
-
const legendLabels = ['DNS Lookup', 'Connection', 'SSL/TLS', 'Request', 'Response'];
|
|
715
|
-
|
|
716
|
-
for (const label of legendLabels) {
|
|
717
|
-
const legendItem = Array.from(legendItems).find((el) => el.textContent?.includes(label));
|
|
718
|
-
if (sampleData[label.toLowerCase().replace(/[^a-z]/g, '')] > 0) {
|
|
719
|
-
await expect(legendItem).toBeInTheDocument();
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
// Check animation data attribute
|
|
724
|
-
const animatedSegments = container.querySelectorAll('[data-animated="true"]');
|
|
725
|
-
await expect(animatedSegments.length).toBeGreaterThan(0);
|
|
726
|
-
|
|
727
|
-
await waitFor(() => {
|
|
728
|
-
const status = document.createElement('div');
|
|
729
|
-
status.setAttribute('aria-label', 'Status of the test run');
|
|
730
|
-
status.textContent = 'PASS';
|
|
731
|
-
canvasElement.appendChild(status);
|
|
732
|
-
});
|
|
733
|
-
},
|
|
734
|
-
};
|