@zap-wunschlachen/wl-shared-components 1.0.25 → 1.0.26
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/.github/workflows/playwright.yml +205 -205
- package/.github/workflows/static.yml +61 -61
- package/.github/workflows/update-snapshots.yml +37 -37
- package/.prettierrc +5 -5
- package/.storybook/main.ts +18 -18
- package/.storybook/preview.ts +37 -37
- package/.storybook/storyWrapper.vue +18 -18
- package/.storybook/withVuetifyTheme.decorator.ts +21 -21
- package/App.vue +34 -176
- package/README.md +56 -56
- package/heroicons.ts +75 -75
- package/index.html +19 -19
- package/package.json +67 -67
- package/playwright.config.ts +48 -48
- package/public/background.svg +60 -60
- package/public/style.css +187 -187
- package/public/technologies.svg +22 -22
- package/src/assets/css/base.css +235 -235
- package/src/assets/css/variables.css +107 -96
- package/src/components/Accordion/Accordion.css +59 -59
- package/src/components/Accordion/AccordionGroup.vue +51 -51
- package/src/components/Accordion/AccordionItem.vue +66 -66
- package/src/components/Appointment/Card/Actions.css +54 -54
- package/src/components/Appointment/Card/Actions.vue +99 -99
- package/src/components/Appointment/Card/AnamneseNotification.css +15 -15
- package/src/components/Appointment/Card/AnamneseNotification.vue +23 -23
- package/src/components/Appointment/Card/Card.css +80 -80
- package/src/components/Appointment/Card/Card.vue +93 -93
- package/src/components/Appointment/Card/Details.css +50 -50
- package/src/components/Appointment/Card/Details.vue +43 -43
- package/src/components/Audio/Audio.vue +187 -187
- package/src/components/Audio/Waveform.vue +117 -117
- package/src/components/Background/Background.css +39 -0
- package/src/components/Background/Background.vue +19 -0
- package/src/components/Background/WhiteCocoonBackground.vue +9 -0
- package/src/components/Background/WunschlachenBackground.vue +11 -0
- package/src/components/Button/Button.vue +119 -119
- package/src/components/CheckBox/CheckBox.css +185 -185
- package/src/components/CheckBox/Checkbox.vue +130 -130
- package/src/components/DateInput/DateInput.css +2 -2
- package/src/components/DateInput/DateInput.vue +262 -262
- package/src/components/Dialog/Dialog.css +6 -6
- package/src/components/Dialog/Dialog.vue +29 -29
- package/src/components/EditField/EditField.css +19 -19
- package/src/components/EditField/EditField.vue +202 -202
- package/src/components/ErrorPage/ErrorPage.css +124 -0
- package/src/components/ErrorPage/ErrorPage.vue +45 -0
- package/src/components/ErrorPage/ErrorPageLogo.vue +26 -0
- package/src/components/IconBullet/IconBullet.vue +86 -86
- package/src/components/IconBullet/IconBulletList.vue +41 -41
- package/src/components/Icons/AdvanceAppointments.vue +153 -153
- package/src/components/Icons/Audio/CloudFailed.vue +20 -20
- package/src/components/Icons/Audio/CloudSaved.vue +21 -21
- package/src/components/Icons/Audio/Delete.vue +15 -15
- package/src/components/Icons/Audio/Pause.vue +18 -18
- package/src/components/Icons/Audio/Play.vue +15 -15
- package/src/components/Icons/CalendarNotification.vue +126 -126
- package/src/components/Icons/Chair.vue +32 -32
- package/src/components/Icons/ChairNotification.vue +35 -35
- package/src/components/Icons/Circle.vue +66 -66
- package/src/components/Icons/FavIcon.vue +22 -22
- package/src/components/Icons/FilledCircle.vue +11 -11
- package/src/components/Icons/Group3.vue +46 -46
- package/src/components/Icons/Logo.vue +108 -0
- package/src/components/Icons/RingNotification.vue +54 -54
- package/src/components/Icons/SolidArrowRight.vue +14 -14
- package/src/components/Icons/calendar.vue +17 -17
- package/src/components/Icons/checkbox.vue +19 -19
- package/src/components/Icons/outlineChecked.vue +27 -27
- package/src/components/Icons/play.vue +5 -5
- package/src/components/Input/Input.css +187 -187
- package/src/components/Input/Input.vue +247 -247
- package/src/components/Laboratory/AppointmentCard/AppointmentCard.css +7 -7
- package/src/components/Laboratory/AppointmentCard/AppointmentCard.vue +116 -116
- package/src/components/Laboratory/ChatBoxImage/ChatBoxImage.vue +81 -81
- package/src/components/Laboratory/ChatMessage/ChatMessage.vue +113 -113
- package/src/components/Laboratory/ChatMessage/ChatMessageBadge.css +4 -4
- package/src/components/Laboratory/ChatMessage/ChatMessageBadge.vue +99 -99
- package/src/components/Laboratory/ChatNotification/ChatNotification.vue +130 -130
- package/src/components/Laboratory/DocumentCard/DocumentCard.css +3 -3
- package/src/components/Laboratory/DocumentCard/DocumentCard.vue +50 -50
- package/src/components/Laboratory/DocumentCard/DocumentCardItem.vue +53 -53
- package/src/components/Laboratory/InfoCard/InfoCard.vue +162 -162
- package/src/components/Laboratory/MainColumnsBar/MainColumnsBar.vue +102 -102
- package/src/components/Laboratory/ProgressCircle/ProgressCircle.vue +152 -152
- package/src/components/Laboratory/ProgressLinear/ProgressLinear.css +33 -33
- package/src/components/Laboratory/ProgressLinear/ProgressLinear.vue +75 -75
- package/src/components/Laboratory/SelectionColumnBar/SelectionColumnBar.vue +92 -92
- package/src/components/Laboratory/StatusNotification/StatusNotification.vue +49 -49
- package/src/components/Laboratory/TagLabel/TagLabel.vue +126 -126
- package/src/components/Laboratory/TagLabelGroup/TagLabelGroup.vue +97 -97
- package/src/components/Laboratory/TicketCard/TicketCard.css +3 -3
- package/src/components/Laboratory/TicketCard/TicketCard.vue +143 -143
- package/src/components/Laboratory/TimeLine/TimeLineEvent.css +18 -18
- package/src/components/Laboratory/TimeLine/TimeLineEvent.vue +119 -119
- package/src/components/Laboratory/TimeLine/Timeline.css +4 -4
- package/src/components/Laboratory/TimeLine/Timeline.vue +30 -30
- package/src/components/Loader/Loader.css +51 -51
- package/src/components/MaintenanceBanner/MaintenanceBanner.css +289 -0
- package/src/components/MaintenanceBanner/MaintenanceBanner.vue +127 -0
- package/src/components/MaintenanceBanner/MaintenanceIllustration.vue +54 -0
- package/src/components/Modal/Modal.css +5 -5
- package/src/components/Modal/Modal.vue +22 -22
- package/src/components/NotificationBubble/NotificationBubble.css +4 -4
- package/src/components/NotificationBubble/NotificationBubble.vue +90 -90
- package/src/components/OtpInput/OtpInput.css +39 -39
- package/src/components/OtpInput/OtpInput.vue +143 -143
- package/src/components/PhoneInput/PhoneInput.css +31 -31
- package/src/components/PhoneInput/PhoneInput.vue +113 -113
- package/src/components/Select/Select.css +150 -150
- package/src/components/Select/Select.vue +315 -315
- package/src/components/TextArea/TextArea.css +3 -3
- package/src/components/TextArea/TextArea.vue +126 -126
- package/src/components/TickBox/TickBox.css +49 -49
- package/src/components/TickBox/TickBox.vue +126 -126
- package/src/components/index.ts +26 -24
- package/src/constants/iconEnums.ts +3 -3
- package/src/i18n/i18n.ts +15 -15
- package/src/i18n/locales/de.json +30 -30
- package/src/i18n/locales/en.json +30 -30
- package/src/index.ts +34 -34
- package/src/main.ts +11 -11
- package/src/plugins/vuetify.ts +139 -131
- package/src/shims-vue.d.ts +10 -10
- package/src/stories/Accordion.stories.ts +650 -650
- package/src/stories/Audio.stories.ts +28 -28
- package/src/stories/Button.stories.ts +263 -263
- package/src/stories/CheckBox.stories.ts +348 -348
- package/src/stories/DateInput.stories.ts +53 -53
- package/src/stories/Dialog.stories.ts +147 -147
- package/src/stories/EditField.stories.ts +78 -78
- package/src/stories/IconBullet/IconBullet.stories.ts +201 -201
- package/src/stories/IconBullet/IconBulletList.stories.ts +275 -275
- package/src/stories/Input.stories.ts +351 -351
- package/src/stories/Laboratory/Cards/AppointmentCard/AppointmentCard.stories.ts +260 -260
- package/src/stories/Laboratory/Cards/DocumentCard/DocumentCard.stories.ts +176 -176
- package/src/stories/Laboratory/Cards/DocumentCard/DocumentCardItem.stories.ts +119 -119
- package/src/stories/Laboratory/Cards/InfoCard/InfoCard.stories.ts +320 -320
- package/src/stories/Laboratory/Cards/TicketCard/TicketCard.stories.ts +335 -335
- package/src/stories/Laboratory/Chat/ChatBoxImage.stories.ts +82 -82
- package/src/stories/Laboratory/Chat/ChatMessage.stories.ts +198 -198
- package/src/stories/Laboratory/Chat/ChatMessageBadge.stories.ts +204 -204
- package/src/stories/Laboratory/Chat/ChatNotification.stories.ts +144 -144
- package/src/stories/Laboratory/Chat/ProgressLinear.stories.ts +186 -186
- package/src/stories/Laboratory/Chat/StatusNotification.stories.ts +111 -111
- package/src/stories/Laboratory/MainColumnsBar.stories.ts +48 -48
- package/src/stories/Laboratory/ProgressCircle.stories.ts +261 -261
- package/src/stories/Laboratory/SelectionColumnBar.stories.ts +234 -234
- package/src/stories/Laboratory/TagLabel.stories.ts +418 -418
- package/src/stories/Laboratory/TagLabelGroup.stories.ts +234 -234
- package/src/stories/Laboratory/Timeline.stories.ts +403 -403
- package/src/stories/NotificationBubble.stories.ts +194 -194
- package/src/stories/OtpInput.stories.ts +100 -100
- package/src/stories/PhoneInput.stories.ts +52 -52
- package/src/stories/Select.stories.ts +419 -419
- package/src/stories/TextArea.stories.ts +112 -112
- package/src/stories/TickBox.stories.ts +294 -294
- package/src/stories/v-icon.stories.ts +91 -91
- package/src/utils/index.ts +106 -100
- package/src/vite-env.d.ts +1 -1
- package/tests/e2e/README.md +220 -220
- package/tests/e2e/accessibility.spec.ts +638 -638
- package/tests/e2e/accordion.spec.ts +42 -42
- package/tests/e2e/additional-components.spec.ts +437 -437
- package/tests/e2e/all-components.spec.ts +135 -135
- package/tests/e2e/appointment-card.spec.ts +816 -816
- package/tests/e2e/button-fixed.spec.ts +58 -58
- package/tests/e2e/button.spec.ts +76 -76
- package/tests/e2e/checkbox.spec.ts +50 -50
- package/tests/e2e/date-input.spec.ts +46 -46
- package/tests/e2e/debug.spec.ts +51 -51
- package/tests/e2e/dialog.spec.ts +58 -58
- package/tests/e2e/input.spec.ts +55 -55
- package/tests/e2e/laboratory-components.spec.ts +320 -320
- package/tests/e2e/otp-input.spec.ts +50 -50
- package/tests/e2e/select.spec.ts +52 -52
- package/tests/e2e/storybook-utils.ts +59 -59
- package/tests/e2e/test-basic.spec.ts +33 -33
- package/tests/e2e/visual-regression.spec.ts +350 -350
- package/tests/unit/components/Accordion/AccordionGroup.spec.ts.skip +342 -342
- package/tests/unit/components/Accordion/AccordionItem.spec.ts.skip +383 -383
- package/tests/unit/components/Appointment/Card/Actions.spec.ts +407 -407
- package/tests/unit/components/Appointment/Card/Card.spec.ts +485 -485
- package/tests/unit/components/Appointment/Card/Details.spec.ts +397 -397
- package/tests/unit/components/Audio/Audio.spec.ts +403 -403
- package/tests/unit/components/Audio/Waveform.spec.ts +483 -483
- package/tests/unit/components/Core/Button.spec.ts +336 -336
- package/tests/unit/components/Core/Checkbox.spec.ts +544 -544
- package/tests/unit/components/Core/DateInput.spec.ts +690 -690
- package/tests/unit/components/Core/Dialog.spec.ts +485 -485
- package/tests/unit/components/Core/EditField.spec.ts +782 -782
- package/tests/unit/components/Core/Input.spec.ts +512 -512
- package/tests/unit/components/Core/Modal.spec.ts +518 -518
- package/tests/unit/components/Core/NotificationBubble.spec.ts +606 -606
- package/tests/unit/components/Core/OtpInput.spec.ts +708 -708
- package/tests/unit/components/Core/PhoneInput.spec.ts +619 -619
- package/tests/unit/components/Core/Select.spec.ts +712 -712
- package/tests/unit/components/Core/TextArea.spec.ts +565 -565
- package/tests/unit/components/Core/TickBox.spec.ts +779 -779
- package/tests/unit/components/IconBullet/IconBullet.spec.ts +356 -356
- package/tests/unit/components/IconBullet/IconBulletList.spec.ts +371 -371
- package/tests/unit/components/Icons/Audio/CloudFailed.spec.ts +108 -108
- package/tests/unit/components/Icons/Audio/CloudSaved.spec.ts +149 -149
- package/tests/unit/components/Icons/Audio/Delete.spec.ts +158 -158
- package/tests/unit/components/Icons/Audio/Pause.spec.ts +208 -208
- package/tests/unit/components/Icons/Audio/Play.spec.ts +217 -217
- package/tests/unit/components/Icons/CalendarNotification.spec.ts +186 -186
- package/tests/unit/components/Icons/Chair.spec.ts +234 -234
- package/tests/unit/components/Icons/ChairNotification.spec.ts +311 -311
- package/tests/unit/components/Icons/Circle.spec.ts +255 -255
- package/tests/unit/components/Icons/FavIcon.spec.ts +251 -251
- package/tests/unit/components/Icons/FilledCircle.spec.ts +274 -274
- package/tests/unit/components/Icons/Group3.spec.ts +355 -355
- package/tests/unit/components/Icons/RingNotification.spec.ts +393 -393
- package/tests/unit/components/Icons/calendar.spec.ts +286 -286
- package/tests/unit/components/Icons/checkbox.spec.ts +315 -315
- package/tests/unit/components/Icons/outlineChecked.spec.ts +434 -434
- package/tests/unit/components/Icons/play.spec.ts +308 -308
- package/tests/unit/components/Laboratory/AppointmentCard.spec.ts +167 -167
- package/tests/unit/components/Laboratory/ChatBoxImage.spec.ts +179 -179
- package/tests/unit/components/Laboratory/ChatMessage.spec.ts +263 -263
- package/tests/unit/components/Laboratory/ChatMessageBadge.spec.ts +282 -282
- package/tests/unit/components/Laboratory/ChatNotification.spec.ts +256 -256
- package/tests/unit/components/Laboratory/DocumentCard.spec.ts +228 -228
- package/tests/unit/components/Laboratory/DocumentCardItem.spec.ts +236 -236
- package/tests/unit/components/Laboratory/InfoCard.spec.ts +308 -308
- package/tests/unit/components/Laboratory/MainColumnsBar.spec.ts +251 -251
- package/tests/unit/components/Laboratory/ProgressCircle.spec.ts +290 -290
- package/tests/unit/components/Laboratory/ProgressLinear.spec.ts +275 -275
- package/tests/unit/components/Laboratory/SelectionColumnBar.spec.ts +288 -288
- package/tests/unit/components/Laboratory/StatusNotification.spec.ts +296 -296
- package/tests/unit/components/Laboratory/TagLabel.spec.ts +353 -353
- package/tests/unit/components/Laboratory/TagLabelGroup.spec.ts +377 -377
- package/tests/unit/components/Laboratory/TicketCard.spec.ts +351 -351
- package/tests/unit/components/Laboratory/TimeLineEvent.spec.ts +381 -381
- package/tests/unit/components/Laboratory/Timeline.spec.ts +419 -419
- package/tests/unit/constants/iconEnums.spec.ts +39 -39
- package/tests/unit/i18n/i18n.spec.ts +88 -88
- package/tests/unit/plugins/vuetify.spec.ts +220 -220
- package/tests/unit/setup.ts +189 -189
- package/tests/unit/src/components/index.spec.ts.skip +192 -192
- package/tests/unit/src/index.spec.ts.skip +182 -182
- package/tests/unit/src/main.spec.ts +151 -151
- package/tsconfig.json +26 -26
- package/vite.config.ts +29 -29
- package/vitest.config.ts +83 -83
|
@@ -1,351 +1,351 @@
|
|
|
1
|
-
import { test, expect, Frame } from '@playwright/test';
|
|
2
|
-
import { navigateToStory, getComponentButton, getComponentInput, getComponentElement } from './storybook-utils';
|
|
3
|
-
|
|
4
|
-
test.describe('Visual Regression Tests', () => {
|
|
5
|
-
let frame: Frame;
|
|
6
|
-
|
|
7
|
-
test.describe('Core Components Visual Tests', () => {
|
|
8
|
-
const coreComponents = [
|
|
9
|
-
{ name: 'Button Default', path: '/?path=/story/wl-button--default' },
|
|
10
|
-
{ name: 'Button Outlined', path: '/?path=/story/wl-button--outlined-variant' },
|
|
11
|
-
{ name: 'Button Loading', path: '/?path=/story/wl-button--loading-state' },
|
|
12
|
-
{ name: 'Button Disabled', path: '/?path=/story/wl-button--disabled-state' },
|
|
13
|
-
{ name: 'Input Default', path: '/?path=/story/wl-input--default' },
|
|
14
|
-
{ name: 'Input Success', path: '/?path=/story/wl-input--success' },
|
|
15
|
-
{ name: 'Input Error', path: '/?path=/story/wl-input--error' },
|
|
16
|
-
{ name: 'Input Warning', path: '/?path=/story/wl-input--warning' },
|
|
17
|
-
{ name: 'Select Default', path: '/?path=/story/wl-select--default' },
|
|
18
|
-
{ name: 'Checkbox Default', path: '/?path=/story/wl-checkbox--default' },
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
coreComponents.forEach(({ name, path }) => {
|
|
22
|
-
test(`${name} visual regression`, async ({ page }) => {
|
|
23
|
-
await page.goto(path);
|
|
24
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 10000 });
|
|
25
|
-
|
|
26
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
27
|
-
if (!frame) throw new Error('Frame not found');
|
|
28
|
-
|
|
29
|
-
await frame.waitForSelector('[data-testid="root"]', { timeout: 10000 });
|
|
30
|
-
|
|
31
|
-
// Wait for any animations to complete
|
|
32
|
-
await page.waitForTimeout(1000);
|
|
33
|
-
|
|
34
|
-
// Hide dynamic content that might cause flakiness
|
|
35
|
-
await frame.addStyleTag({
|
|
36
|
-
content: `
|
|
37
|
-
/* Hide potentially dynamic content */
|
|
38
|
-
.v-tooltip { display: none !important; }
|
|
39
|
-
.v-overlay { display: none !important; }
|
|
40
|
-
[role="tooltip"] { display: none !important; }
|
|
41
|
-
.loading-spinner { animation: none !important; }
|
|
42
|
-
`
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot(`${name.toLowerCase().replace(/\s+/g, '-')}.png`, {
|
|
46
|
-
animations: 'disabled',
|
|
47
|
-
caret: 'hide'
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test.describe('Form Components Visual Tests', () => {
|
|
54
|
-
const formComponents = [
|
|
55
|
-
{ name: 'DateInput Default', path: '/?path=/story/wl-dateinput--default' },
|
|
56
|
-
{ name: 'OtpInput Default', path: '/?path=/story/wl-otpinput--default' },
|
|
57
|
-
{ name: 'PhoneInput Default', path: '/?path=/story/wl-phoneinput--default' },
|
|
58
|
-
{ name: 'TextArea Default', path: '/?path=/story/wl-textarea--default' },
|
|
59
|
-
{ name: 'EditField Default', path: '/?path=/story/wl-editfield--text-field' },
|
|
60
|
-
];
|
|
61
|
-
|
|
62
|
-
formComponents.forEach(({ name, path }) => {
|
|
63
|
-
test(`${name} visual regression`, async ({ page }) => {
|
|
64
|
-
await page.goto(path);
|
|
65
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 10000 });
|
|
66
|
-
|
|
67
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
68
|
-
if (!frame) throw new Error('Frame not found');
|
|
69
|
-
|
|
70
|
-
await frame.waitForSelector('[data-testid="root"]', { timeout: 10000 });
|
|
71
|
-
|
|
72
|
-
await page.waitForTimeout(1000);
|
|
73
|
-
|
|
74
|
-
await frame.addStyleTag({
|
|
75
|
-
content: `
|
|
76
|
-
.v-tooltip { display: none !important; }
|
|
77
|
-
.v-overlay { display: none !important; }
|
|
78
|
-
[role="tooltip"] { display: none !important; }
|
|
79
|
-
`
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot(`${name.toLowerCase().replace(/\s+/g, '-')}.png`, {
|
|
83
|
-
animations: 'disabled',
|
|
84
|
-
caret: 'hide'
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test.describe('UI Components Visual Tests', () => {
|
|
91
|
-
const uiComponents = [
|
|
92
|
-
{ name: 'Accordion Default', path: '/?path=/story/wl-accordion--outlined-inset' },
|
|
93
|
-
{ name: 'Dialog Default', path: '/?path=/story/wl-dialog--default-dialog' },
|
|
94
|
-
// Modal component doesn't exist in stories - removing
|
|
95
|
-
// { name: 'Modal Default', path: '/?path=/story/wl-modal--default' },
|
|
96
|
-
{ name: 'NotificationBubble Default', path: '/?path=/story/wl-notificationbubble--default' },
|
|
97
|
-
{ name: 'TickBox Default', path: '/?path=/story/wl-tickbox--default' },
|
|
98
|
-
];
|
|
99
|
-
|
|
100
|
-
uiComponents.forEach(({ name, path }) => {
|
|
101
|
-
test(`${name} visual regression`, async ({ page }) => {
|
|
102
|
-
await page.goto(path);
|
|
103
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 10000 });
|
|
104
|
-
|
|
105
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
106
|
-
if (!frame) throw new Error('Frame not found');
|
|
107
|
-
|
|
108
|
-
await frame.waitForSelector('[data-testid="root"]', { timeout: 10000 });
|
|
109
|
-
|
|
110
|
-
await page.waitForTimeout(1000);
|
|
111
|
-
|
|
112
|
-
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot(`${name.toLowerCase().replace(/\s+/g, '-')}.png`, {
|
|
113
|
-
animations: 'disabled',
|
|
114
|
-
caret: 'hide'
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
test.describe('Laboratory Components Visual Tests', () => {
|
|
121
|
-
const labComponents = [
|
|
122
|
-
{ name: 'AppointmentCard', path: '/?path=/story/wl-laboratory-cards-appointmentcard--draft-status' },
|
|
123
|
-
{ name: 'DocumentCard', path: '/?path=/story/wl-laboratory-cards-documentcard-documentcard--default' },
|
|
124
|
-
{ name: 'InfoCard', path: '/?path=/story/wl-laboratory-cards-infocard--draft-done' },
|
|
125
|
-
{ name: 'TicketCard', path: '/?path=/story/wl-laboratory-cards-ticketcard--default' },
|
|
126
|
-
{ name: 'ChatMessage', path: '/?path=/story/wl-laboratory-chat-chatmessage--income-message' },
|
|
127
|
-
{ name: 'ChatNotification', path: '/?path=/story/wl-laboratory-chat-chatnotification--empty' },
|
|
128
|
-
{ name: 'ProgressCircle', path: '/?path=/story/wl-laboratory-progresscircle--default' },
|
|
129
|
-
{ name: 'TagLabel', path: '/?path=/story/wl-laboratory-taglabel--draft' },
|
|
130
|
-
// TagLabelGroup doesn't have its own stories - removing
|
|
131
|
-
// { name: 'TagLabelGroup', path: '/?path=/story/laboratory-taglabelgroup--default' },
|
|
132
|
-
// Timeline doesn't have its own stories - removing
|
|
133
|
-
// { name: 'Timeline', path: '/?path=/story/laboratory-timeline--default' },
|
|
134
|
-
];
|
|
135
|
-
|
|
136
|
-
labComponents.forEach(({ name, path }) => {
|
|
137
|
-
test(`${name} visual regression`, async ({ page }) => {
|
|
138
|
-
await page.goto(path);
|
|
139
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 10000 });
|
|
140
|
-
|
|
141
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
142
|
-
if (!frame) throw new Error('Frame not found');
|
|
143
|
-
|
|
144
|
-
await frame.waitForSelector('[data-testid="root"]', { timeout: 10000 });
|
|
145
|
-
|
|
146
|
-
await page.waitForTimeout(1000);
|
|
147
|
-
|
|
148
|
-
await frame.addStyleTag({
|
|
149
|
-
content: `
|
|
150
|
-
.v-tooltip { display: none !important; }
|
|
151
|
-
[role="tooltip"] { display: none !important; }
|
|
152
|
-
.loading-spinner { animation: none !important; }
|
|
153
|
-
.v-progress-circular { animation: none !important; }
|
|
154
|
-
`
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot(`lab-${name.toLowerCase()}.png`, {
|
|
158
|
-
animations: 'disabled',
|
|
159
|
-
caret: 'hide'
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
test.describe('Component States Visual Tests', () => {
|
|
166
|
-
test('button states comparison', async ({ page }) => {
|
|
167
|
-
frame = await navigateToStory(page, '/?path=/story/wl-button--default');
|
|
168
|
-
|
|
169
|
-
// Create a composite screenshot of different button states
|
|
170
|
-
await page.addStyleTag({
|
|
171
|
-
content: `
|
|
172
|
-
body {
|
|
173
|
-
display: flex !important;
|
|
174
|
-
gap: 20px !important;
|
|
175
|
-
padding: 20px !important;
|
|
176
|
-
background: white !important;
|
|
177
|
-
}
|
|
178
|
-
`
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
await expect(page).toHaveScreenshot('button-states-composite.png', {
|
|
182
|
-
fullPage: false,
|
|
183
|
-
animations: 'disabled'
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
test('input validation states', async ({ page }) => {
|
|
188
|
-
const states = ['default', 'success', 'error', 'warning'];
|
|
189
|
-
|
|
190
|
-
for (const state of states) {
|
|
191
|
-
try {
|
|
192
|
-
await page.goto(`/?path=/story/wl-input--${state}`);
|
|
193
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 5000 });
|
|
194
|
-
|
|
195
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
196
|
-
if (!frame) throw new Error('Frame not found');
|
|
197
|
-
|
|
198
|
-
await frame.waitForSelector('[data-testid="root"]', { timeout: 5000 });
|
|
199
|
-
await page.waitForTimeout(500);
|
|
200
|
-
|
|
201
|
-
await expect(frame.locator('[data-testid="root"]')).toHaveScreenshot(`input-state-${state}.png`, {
|
|
202
|
-
animations: 'disabled',
|
|
203
|
-
caret: 'hide'
|
|
204
|
-
});
|
|
205
|
-
} catch (error) {
|
|
206
|
-
console.log(`Input state ${state} test skipped`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
test.describe('Responsive Visual Tests', () => {
|
|
213
|
-
const viewports = [
|
|
214
|
-
{ name: 'Mobile', width: 375, height: 667 },
|
|
215
|
-
{ name: 'Tablet', width: 768, height: 1024 },
|
|
216
|
-
{ name: 'Desktop', width: 1200, height: 800 }
|
|
217
|
-
];
|
|
218
|
-
|
|
219
|
-
const responsiveComponents = [
|
|
220
|
-
'/?path=/story/wl-button--default',
|
|
221
|
-
'/?path=/story/wl-input--default',
|
|
222
|
-
'/?path=/story/wl-laboratory-cards-appointmentcard--draft-status'
|
|
223
|
-
];
|
|
224
|
-
|
|
225
|
-
viewports.forEach(({ name, width, height }) => {
|
|
226
|
-
responsiveComponents.forEach((component, index) => {
|
|
227
|
-
test(`responsive ${name.toLowerCase()} - component ${index + 1}`, async ({ page }) => {
|
|
228
|
-
await page.setViewportSize({ width, height });
|
|
229
|
-
|
|
230
|
-
try {
|
|
231
|
-
await page.goto(component);
|
|
232
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 5000 });
|
|
233
|
-
|
|
234
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
235
|
-
if (!frame) throw new Error('Frame not found');
|
|
236
|
-
|
|
237
|
-
await frame.waitForSelector('[data-testid="root"]', { timeout: 5000 });
|
|
238
|
-
await page.waitForTimeout(1000);
|
|
239
|
-
|
|
240
|
-
await expect(frame.locator('[data-testid="root"]')).toHaveScreenshot(`responsive-${name.toLowerCase()}-component-${index + 1}.png`, {
|
|
241
|
-
animations: 'disabled'
|
|
242
|
-
});
|
|
243
|
-
} catch (error) {
|
|
244
|
-
console.log(`Responsive test skipped for ${component} on ${name}`);
|
|
245
|
-
test.skip();
|
|
246
|
-
}
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
test.describe('Dark Mode Visual Tests', () => {
|
|
253
|
-
test.beforeEach(async ({ page }) => {
|
|
254
|
-
// Enable dark mode if supported
|
|
255
|
-
await page.addStyleTag({
|
|
256
|
-
content: `
|
|
257
|
-
:root { color-scheme: dark; }
|
|
258
|
-
body { background: #1a1a1a; color: white; }
|
|
259
|
-
.v-theme--light {
|
|
260
|
-
background: #1a1a1a !important;
|
|
261
|
-
color: white !important;
|
|
262
|
-
}
|
|
263
|
-
`
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
const darkModeComponents = [
|
|
268
|
-
'/?path=/story/wl-button--default',
|
|
269
|
-
'/?path=/story/wl-input--default',
|
|
270
|
-
'/?path=/story/wl-select--default'
|
|
271
|
-
];
|
|
272
|
-
|
|
273
|
-
darkModeComponents.forEach((component, index) => {
|
|
274
|
-
test(`dark mode component ${index + 1}`, async ({ page }) => {
|
|
275
|
-
try {
|
|
276
|
-
await page.goto(component);
|
|
277
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 5000 });
|
|
278
|
-
|
|
279
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
280
|
-
if (!frame) throw new Error('Frame not found');
|
|
281
|
-
|
|
282
|
-
await frame.waitForSelector('[data-testid="root"]', { timeout: 5000 });
|
|
283
|
-
await page.waitForTimeout(1000);
|
|
284
|
-
|
|
285
|
-
await expect(frame.locator('[data-testid="root"]')).toHaveScreenshot(`dark-mode-component-${index + 1}.png`, {
|
|
286
|
-
animations: 'disabled'
|
|
287
|
-
});
|
|
288
|
-
} catch (error) {
|
|
289
|
-
console.log(`Dark mode test skipped for ${component}`);
|
|
290
|
-
test.skip();
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
});
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
test.describe('Interactive States Visual Tests', () => {
|
|
297
|
-
test('button hover and focus states', async ({ page }) => {
|
|
298
|
-
frame = await navigateToStory(page, '/?path=/story/wl-button--default');
|
|
299
|
-
|
|
300
|
-
// Find the actual button component, not the "Set string" button
|
|
301
|
-
const button = frame.locator('button.v-btn').filter({ hasNotText: 'Set string' }).first();
|
|
302
|
-
|
|
303
|
-
// Normal state
|
|
304
|
-
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot('button-normal-state.png', {
|
|
305
|
-
animations: 'disabled'
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
// Hover state
|
|
309
|
-
await button.hover();
|
|
310
|
-
await page.waitForTimeout(300);
|
|
311
|
-
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot('button-hover-state.png', {
|
|
312
|
-
animations: 'disabled'
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
// Focus state
|
|
316
|
-
await button.focus();
|
|
317
|
-
await page.waitForTimeout(300);
|
|
318
|
-
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot('button-focus-state.png', {
|
|
319
|
-
animations: 'disabled'
|
|
320
|
-
});
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
test('input focus and filled states', async ({ page }) => {
|
|
324
|
-
frame = await navigateToStory(page, '/?path=/story/wl-input--default');
|
|
325
|
-
|
|
326
|
-
const input = frame.locator('input, .v-field input').first();
|
|
327
|
-
|
|
328
|
-
// Normal state
|
|
329
|
-
await expect(page).toHaveScreenshot('input-normal-state.png', {
|
|
330
|
-
animations: 'disabled',
|
|
331
|
-
caret: 'hide'
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
// Focus state
|
|
335
|
-
await input.focus();
|
|
336
|
-
await page.waitForTimeout(300);
|
|
337
|
-
await expect(page).toHaveScreenshot('input-focus-state.png', {
|
|
338
|
-
animations: 'disabled',
|
|
339
|
-
caret: 'hide'
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
// Filled state
|
|
343
|
-
await input.fill('Sample text');
|
|
344
|
-
await page.waitForTimeout(300);
|
|
345
|
-
await expect(page).toHaveScreenshot('input-filled-state.png', {
|
|
346
|
-
animations: 'disabled',
|
|
347
|
-
caret: 'hide'
|
|
348
|
-
});
|
|
349
|
-
});
|
|
350
|
-
});
|
|
1
|
+
import { test, expect, Frame } from '@playwright/test';
|
|
2
|
+
import { navigateToStory, getComponentButton, getComponentInput, getComponentElement } from './storybook-utils';
|
|
3
|
+
|
|
4
|
+
test.describe('Visual Regression Tests', () => {
|
|
5
|
+
let frame: Frame;
|
|
6
|
+
|
|
7
|
+
test.describe('Core Components Visual Tests', () => {
|
|
8
|
+
const coreComponents = [
|
|
9
|
+
{ name: 'Button Default', path: '/?path=/story/wl-button--default' },
|
|
10
|
+
{ name: 'Button Outlined', path: '/?path=/story/wl-button--outlined-variant' },
|
|
11
|
+
{ name: 'Button Loading', path: '/?path=/story/wl-button--loading-state' },
|
|
12
|
+
{ name: 'Button Disabled', path: '/?path=/story/wl-button--disabled-state' },
|
|
13
|
+
{ name: 'Input Default', path: '/?path=/story/wl-input--default' },
|
|
14
|
+
{ name: 'Input Success', path: '/?path=/story/wl-input--success' },
|
|
15
|
+
{ name: 'Input Error', path: '/?path=/story/wl-input--error' },
|
|
16
|
+
{ name: 'Input Warning', path: '/?path=/story/wl-input--warning' },
|
|
17
|
+
{ name: 'Select Default', path: '/?path=/story/wl-select--default' },
|
|
18
|
+
{ name: 'Checkbox Default', path: '/?path=/story/wl-checkbox--default' },
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
coreComponents.forEach(({ name, path }) => {
|
|
22
|
+
test(`${name} visual regression`, async ({ page }) => {
|
|
23
|
+
await page.goto(path);
|
|
24
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 10000 });
|
|
25
|
+
|
|
26
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
27
|
+
if (!frame) throw new Error('Frame not found');
|
|
28
|
+
|
|
29
|
+
await frame.waitForSelector('[data-testid="root"]', { timeout: 10000 });
|
|
30
|
+
|
|
31
|
+
// Wait for any animations to complete
|
|
32
|
+
await page.waitForTimeout(1000);
|
|
33
|
+
|
|
34
|
+
// Hide dynamic content that might cause flakiness
|
|
35
|
+
await frame.addStyleTag({
|
|
36
|
+
content: `
|
|
37
|
+
/* Hide potentially dynamic content */
|
|
38
|
+
.v-tooltip { display: none !important; }
|
|
39
|
+
.v-overlay { display: none !important; }
|
|
40
|
+
[role="tooltip"] { display: none !important; }
|
|
41
|
+
.loading-spinner { animation: none !important; }
|
|
42
|
+
`
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot(`${name.toLowerCase().replace(/\s+/g, '-')}.png`, {
|
|
46
|
+
animations: 'disabled',
|
|
47
|
+
caret: 'hide'
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test.describe('Form Components Visual Tests', () => {
|
|
54
|
+
const formComponents = [
|
|
55
|
+
{ name: 'DateInput Default', path: '/?path=/story/wl-dateinput--default' },
|
|
56
|
+
{ name: 'OtpInput Default', path: '/?path=/story/wl-otpinput--default' },
|
|
57
|
+
{ name: 'PhoneInput Default', path: '/?path=/story/wl-phoneinput--default' },
|
|
58
|
+
{ name: 'TextArea Default', path: '/?path=/story/wl-textarea--default' },
|
|
59
|
+
{ name: 'EditField Default', path: '/?path=/story/wl-editfield--text-field' },
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
formComponents.forEach(({ name, path }) => {
|
|
63
|
+
test(`${name} visual regression`, async ({ page }) => {
|
|
64
|
+
await page.goto(path);
|
|
65
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 10000 });
|
|
66
|
+
|
|
67
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
68
|
+
if (!frame) throw new Error('Frame not found');
|
|
69
|
+
|
|
70
|
+
await frame.waitForSelector('[data-testid="root"]', { timeout: 10000 });
|
|
71
|
+
|
|
72
|
+
await page.waitForTimeout(1000);
|
|
73
|
+
|
|
74
|
+
await frame.addStyleTag({
|
|
75
|
+
content: `
|
|
76
|
+
.v-tooltip { display: none !important; }
|
|
77
|
+
.v-overlay { display: none !important; }
|
|
78
|
+
[role="tooltip"] { display: none !important; }
|
|
79
|
+
`
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot(`${name.toLowerCase().replace(/\s+/g, '-')}.png`, {
|
|
83
|
+
animations: 'disabled',
|
|
84
|
+
caret: 'hide'
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test.describe('UI Components Visual Tests', () => {
|
|
91
|
+
const uiComponents = [
|
|
92
|
+
{ name: 'Accordion Default', path: '/?path=/story/wl-accordion--outlined-inset' },
|
|
93
|
+
{ name: 'Dialog Default', path: '/?path=/story/wl-dialog--default-dialog' },
|
|
94
|
+
// Modal component doesn't exist in stories - removing
|
|
95
|
+
// { name: 'Modal Default', path: '/?path=/story/wl-modal--default' },
|
|
96
|
+
{ name: 'NotificationBubble Default', path: '/?path=/story/wl-notificationbubble--default' },
|
|
97
|
+
{ name: 'TickBox Default', path: '/?path=/story/wl-tickbox--default' },
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
uiComponents.forEach(({ name, path }) => {
|
|
101
|
+
test(`${name} visual regression`, async ({ page }) => {
|
|
102
|
+
await page.goto(path);
|
|
103
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 10000 });
|
|
104
|
+
|
|
105
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
106
|
+
if (!frame) throw new Error('Frame not found');
|
|
107
|
+
|
|
108
|
+
await frame.waitForSelector('[data-testid="root"]', { timeout: 10000 });
|
|
109
|
+
|
|
110
|
+
await page.waitForTimeout(1000);
|
|
111
|
+
|
|
112
|
+
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot(`${name.toLowerCase().replace(/\s+/g, '-')}.png`, {
|
|
113
|
+
animations: 'disabled',
|
|
114
|
+
caret: 'hide'
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test.describe('Laboratory Components Visual Tests', () => {
|
|
121
|
+
const labComponents = [
|
|
122
|
+
{ name: 'AppointmentCard', path: '/?path=/story/wl-laboratory-cards-appointmentcard--draft-status' },
|
|
123
|
+
{ name: 'DocumentCard', path: '/?path=/story/wl-laboratory-cards-documentcard-documentcard--default' },
|
|
124
|
+
{ name: 'InfoCard', path: '/?path=/story/wl-laboratory-cards-infocard--draft-done' },
|
|
125
|
+
{ name: 'TicketCard', path: '/?path=/story/wl-laboratory-cards-ticketcard--default' },
|
|
126
|
+
{ name: 'ChatMessage', path: '/?path=/story/wl-laboratory-chat-chatmessage--income-message' },
|
|
127
|
+
{ name: 'ChatNotification', path: '/?path=/story/wl-laboratory-chat-chatnotification--empty' },
|
|
128
|
+
{ name: 'ProgressCircle', path: '/?path=/story/wl-laboratory-progresscircle--default' },
|
|
129
|
+
{ name: 'TagLabel', path: '/?path=/story/wl-laboratory-taglabel--draft' },
|
|
130
|
+
// TagLabelGroup doesn't have its own stories - removing
|
|
131
|
+
// { name: 'TagLabelGroup', path: '/?path=/story/laboratory-taglabelgroup--default' },
|
|
132
|
+
// Timeline doesn't have its own stories - removing
|
|
133
|
+
// { name: 'Timeline', path: '/?path=/story/laboratory-timeline--default' },
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
labComponents.forEach(({ name, path }) => {
|
|
137
|
+
test(`${name} visual regression`, async ({ page }) => {
|
|
138
|
+
await page.goto(path);
|
|
139
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 10000 });
|
|
140
|
+
|
|
141
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
142
|
+
if (!frame) throw new Error('Frame not found');
|
|
143
|
+
|
|
144
|
+
await frame.waitForSelector('[data-testid="root"]', { timeout: 10000 });
|
|
145
|
+
|
|
146
|
+
await page.waitForTimeout(1000);
|
|
147
|
+
|
|
148
|
+
await frame.addStyleTag({
|
|
149
|
+
content: `
|
|
150
|
+
.v-tooltip { display: none !important; }
|
|
151
|
+
[role="tooltip"] { display: none !important; }
|
|
152
|
+
.loading-spinner { animation: none !important; }
|
|
153
|
+
.v-progress-circular { animation: none !important; }
|
|
154
|
+
`
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot(`lab-${name.toLowerCase()}.png`, {
|
|
158
|
+
animations: 'disabled',
|
|
159
|
+
caret: 'hide'
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
test.describe('Component States Visual Tests', () => {
|
|
166
|
+
test('button states comparison', async ({ page }) => {
|
|
167
|
+
frame = await navigateToStory(page, '/?path=/story/wl-button--default');
|
|
168
|
+
|
|
169
|
+
// Create a composite screenshot of different button states
|
|
170
|
+
await page.addStyleTag({
|
|
171
|
+
content: `
|
|
172
|
+
body {
|
|
173
|
+
display: flex !important;
|
|
174
|
+
gap: 20px !important;
|
|
175
|
+
padding: 20px !important;
|
|
176
|
+
background: white !important;
|
|
177
|
+
}
|
|
178
|
+
`
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
await expect(page).toHaveScreenshot('button-states-composite.png', {
|
|
182
|
+
fullPage: false,
|
|
183
|
+
animations: 'disabled'
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test('input validation states', async ({ page }) => {
|
|
188
|
+
const states = ['default', 'success', 'error', 'warning'];
|
|
189
|
+
|
|
190
|
+
for (const state of states) {
|
|
191
|
+
try {
|
|
192
|
+
await page.goto(`/?path=/story/wl-input--${state}`);
|
|
193
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 5000 });
|
|
194
|
+
|
|
195
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
196
|
+
if (!frame) throw new Error('Frame not found');
|
|
197
|
+
|
|
198
|
+
await frame.waitForSelector('[data-testid="root"]', { timeout: 5000 });
|
|
199
|
+
await page.waitForTimeout(500);
|
|
200
|
+
|
|
201
|
+
await expect(frame.locator('[data-testid="root"]')).toHaveScreenshot(`input-state-${state}.png`, {
|
|
202
|
+
animations: 'disabled',
|
|
203
|
+
caret: 'hide'
|
|
204
|
+
});
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.log(`Input state ${state} test skipped`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test.describe('Responsive Visual Tests', () => {
|
|
213
|
+
const viewports = [
|
|
214
|
+
{ name: 'Mobile', width: 375, height: 667 },
|
|
215
|
+
{ name: 'Tablet', width: 768, height: 1024 },
|
|
216
|
+
{ name: 'Desktop', width: 1200, height: 800 }
|
|
217
|
+
];
|
|
218
|
+
|
|
219
|
+
const responsiveComponents = [
|
|
220
|
+
'/?path=/story/wl-button--default',
|
|
221
|
+
'/?path=/story/wl-input--default',
|
|
222
|
+
'/?path=/story/wl-laboratory-cards-appointmentcard--draft-status'
|
|
223
|
+
];
|
|
224
|
+
|
|
225
|
+
viewports.forEach(({ name, width, height }) => {
|
|
226
|
+
responsiveComponents.forEach((component, index) => {
|
|
227
|
+
test(`responsive ${name.toLowerCase()} - component ${index + 1}`, async ({ page }) => {
|
|
228
|
+
await page.setViewportSize({ width, height });
|
|
229
|
+
|
|
230
|
+
try {
|
|
231
|
+
await page.goto(component);
|
|
232
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 5000 });
|
|
233
|
+
|
|
234
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
235
|
+
if (!frame) throw new Error('Frame not found');
|
|
236
|
+
|
|
237
|
+
await frame.waitForSelector('[data-testid="root"]', { timeout: 5000 });
|
|
238
|
+
await page.waitForTimeout(1000);
|
|
239
|
+
|
|
240
|
+
await expect(frame.locator('[data-testid="root"]')).toHaveScreenshot(`responsive-${name.toLowerCase()}-component-${index + 1}.png`, {
|
|
241
|
+
animations: 'disabled'
|
|
242
|
+
});
|
|
243
|
+
} catch (error) {
|
|
244
|
+
console.log(`Responsive test skipped for ${component} on ${name}`);
|
|
245
|
+
test.skip();
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
test.describe('Dark Mode Visual Tests', () => {
|
|
253
|
+
test.beforeEach(async ({ page }) => {
|
|
254
|
+
// Enable dark mode if supported
|
|
255
|
+
await page.addStyleTag({
|
|
256
|
+
content: `
|
|
257
|
+
:root { color-scheme: dark; }
|
|
258
|
+
body { background: #1a1a1a; color: white; }
|
|
259
|
+
.v-theme--light {
|
|
260
|
+
background: #1a1a1a !important;
|
|
261
|
+
color: white !important;
|
|
262
|
+
}
|
|
263
|
+
`
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
const darkModeComponents = [
|
|
268
|
+
'/?path=/story/wl-button--default',
|
|
269
|
+
'/?path=/story/wl-input--default',
|
|
270
|
+
'/?path=/story/wl-select--default'
|
|
271
|
+
];
|
|
272
|
+
|
|
273
|
+
darkModeComponents.forEach((component, index) => {
|
|
274
|
+
test(`dark mode component ${index + 1}`, async ({ page }) => {
|
|
275
|
+
try {
|
|
276
|
+
await page.goto(component);
|
|
277
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 5000 });
|
|
278
|
+
|
|
279
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
280
|
+
if (!frame) throw new Error('Frame not found');
|
|
281
|
+
|
|
282
|
+
await frame.waitForSelector('[data-testid="root"]', { timeout: 5000 });
|
|
283
|
+
await page.waitForTimeout(1000);
|
|
284
|
+
|
|
285
|
+
await expect(frame.locator('[data-testid="root"]')).toHaveScreenshot(`dark-mode-component-${index + 1}.png`, {
|
|
286
|
+
animations: 'disabled'
|
|
287
|
+
});
|
|
288
|
+
} catch (error) {
|
|
289
|
+
console.log(`Dark mode test skipped for ${component}`);
|
|
290
|
+
test.skip();
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
test.describe('Interactive States Visual Tests', () => {
|
|
297
|
+
test('button hover and focus states', async ({ page }) => {
|
|
298
|
+
frame = await navigateToStory(page, '/?path=/story/wl-button--default');
|
|
299
|
+
|
|
300
|
+
// Find the actual button component, not the "Set string" button
|
|
301
|
+
const button = frame.locator('button.v-btn').filter({ hasNotText: 'Set string' }).first();
|
|
302
|
+
|
|
303
|
+
// Normal state
|
|
304
|
+
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot('button-normal-state.png', {
|
|
305
|
+
animations: 'disabled'
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// Hover state
|
|
309
|
+
await button.hover();
|
|
310
|
+
await page.waitForTimeout(300);
|
|
311
|
+
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot('button-hover-state.png', {
|
|
312
|
+
animations: 'disabled'
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// Focus state
|
|
316
|
+
await button.focus();
|
|
317
|
+
await page.waitForTimeout(300);
|
|
318
|
+
await expect(frame.locator('[data-testid="root"]').first()).toHaveScreenshot('button-focus-state.png', {
|
|
319
|
+
animations: 'disabled'
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
test('input focus and filled states', async ({ page }) => {
|
|
324
|
+
frame = await navigateToStory(page, '/?path=/story/wl-input--default');
|
|
325
|
+
|
|
326
|
+
const input = frame.locator('input, .v-field input').first();
|
|
327
|
+
|
|
328
|
+
// Normal state
|
|
329
|
+
await expect(page).toHaveScreenshot('input-normal-state.png', {
|
|
330
|
+
animations: 'disabled',
|
|
331
|
+
caret: 'hide'
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// Focus state
|
|
335
|
+
await input.focus();
|
|
336
|
+
await page.waitForTimeout(300);
|
|
337
|
+
await expect(page).toHaveScreenshot('input-focus-state.png', {
|
|
338
|
+
animations: 'disabled',
|
|
339
|
+
caret: 'hide'
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// Filled state
|
|
343
|
+
await input.fill('Sample text');
|
|
344
|
+
await page.waitForTimeout(300);
|
|
345
|
+
await expect(page).toHaveScreenshot('input-filled-state.png', {
|
|
346
|
+
animations: 'disabled',
|
|
347
|
+
caret: 'hide'
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
351
|
});
|