@zap-wunschlachen/wl-shared-components 1.0.24 → 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 -304
- 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,59 +1,59 @@
|
|
|
1
|
-
import { test, expect } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
test.describe('Button Component', () => {
|
|
4
|
-
test('renders default button', async ({ page }) => {
|
|
5
|
-
await page.goto('http://localhost:7000/?path=/story/wl-button--default');
|
|
6
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
7
|
-
|
|
8
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
9
|
-
if (!frame) throw new Error('Frame not found');
|
|
10
|
-
|
|
11
|
-
await frame.waitForSelector('body', { timeout: 10000 });
|
|
12
|
-
const button = frame.locator('button.v-btn:visible').first();
|
|
13
|
-
await expect(button).toBeVisible();
|
|
14
|
-
await expect(button).toHaveText('Button');
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
test('can be clicked', async ({ page }) => {
|
|
18
|
-
await page.goto('http://localhost:7000/?path=/story/wl-button--default');
|
|
19
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
20
|
-
|
|
21
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
22
|
-
if (!frame) throw new Error('Frame not found');
|
|
23
|
-
|
|
24
|
-
await frame.waitForSelector('body', { timeout: 10000 });
|
|
25
|
-
const button = frame.locator('button.v-btn:visible').first();
|
|
26
|
-
await button.click();
|
|
27
|
-
await expect(button).toBeVisible();
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test('displays prepend icon', async ({ page }) => {
|
|
31
|
-
await page.goto('http://localhost:7000/?path=/story/wl-button--with-prepend-icon');
|
|
32
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
33
|
-
|
|
34
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
35
|
-
if (!frame) throw new Error('Frame not found');
|
|
36
|
-
|
|
37
|
-
await frame.waitForSelector('body', { timeout: 10000 });
|
|
38
|
-
const button = frame.locator('button.v-btn:visible').first();
|
|
39
|
-
await expect(button).toBeVisible();
|
|
40
|
-
const icon = button.locator('i').first();
|
|
41
|
-
await expect(icon).toBeVisible();
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('shows loading state', async ({ page }) => {
|
|
45
|
-
await page.goto('http://localhost:7000/?path=/story/wl-button--loading-state');
|
|
46
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
47
|
-
|
|
48
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
49
|
-
if (!frame) throw new Error('Frame not found');
|
|
50
|
-
|
|
51
|
-
await frame.waitForSelector('body', { timeout: 10000 });
|
|
52
|
-
const button = frame.locator('button.v-btn:visible').first();
|
|
53
|
-
await expect(button).toBeVisible();
|
|
54
|
-
await expect(button).toHaveText('Loading...');
|
|
55
|
-
|
|
56
|
-
const loadingSpinner = frame.locator('.v-progress-circular').first();
|
|
57
|
-
await expect(loadingSpinner).toBeVisible();
|
|
58
|
-
});
|
|
1
|
+
import { test, expect } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
test.describe('Button Component', () => {
|
|
4
|
+
test('renders default button', async ({ page }) => {
|
|
5
|
+
await page.goto('http://localhost:7000/?path=/story/wl-button--default');
|
|
6
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
7
|
+
|
|
8
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
9
|
+
if (!frame) throw new Error('Frame not found');
|
|
10
|
+
|
|
11
|
+
await frame.waitForSelector('body', { timeout: 10000 });
|
|
12
|
+
const button = frame.locator('button.v-btn:visible').first();
|
|
13
|
+
await expect(button).toBeVisible();
|
|
14
|
+
await expect(button).toHaveText('Button');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('can be clicked', async ({ page }) => {
|
|
18
|
+
await page.goto('http://localhost:7000/?path=/story/wl-button--default');
|
|
19
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
20
|
+
|
|
21
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
22
|
+
if (!frame) throw new Error('Frame not found');
|
|
23
|
+
|
|
24
|
+
await frame.waitForSelector('body', { timeout: 10000 });
|
|
25
|
+
const button = frame.locator('button.v-btn:visible').first();
|
|
26
|
+
await button.click();
|
|
27
|
+
await expect(button).toBeVisible();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('displays prepend icon', async ({ page }) => {
|
|
31
|
+
await page.goto('http://localhost:7000/?path=/story/wl-button--with-prepend-icon');
|
|
32
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
33
|
+
|
|
34
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
35
|
+
if (!frame) throw new Error('Frame not found');
|
|
36
|
+
|
|
37
|
+
await frame.waitForSelector('body', { timeout: 10000 });
|
|
38
|
+
const button = frame.locator('button.v-btn:visible').first();
|
|
39
|
+
await expect(button).toBeVisible();
|
|
40
|
+
const icon = button.locator('i').first();
|
|
41
|
+
await expect(icon).toBeVisible();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('shows loading state', async ({ page }) => {
|
|
45
|
+
await page.goto('http://localhost:7000/?path=/story/wl-button--loading-state');
|
|
46
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
47
|
+
|
|
48
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
49
|
+
if (!frame) throw new Error('Frame not found');
|
|
50
|
+
|
|
51
|
+
await frame.waitForSelector('body', { timeout: 10000 });
|
|
52
|
+
const button = frame.locator('button.v-btn:visible').first();
|
|
53
|
+
await expect(button).toBeVisible();
|
|
54
|
+
await expect(button).toHaveText('Loading...');
|
|
55
|
+
|
|
56
|
+
const loadingSpinner = frame.locator('.v-progress-circular').first();
|
|
57
|
+
await expect(loadingSpinner).toBeVisible();
|
|
58
|
+
});
|
|
59
59
|
});
|
package/tests/e2e/button.spec.ts
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
import { test, expect } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
test.describe('Button Component', () => {
|
|
4
|
-
async function getFrame(page) {
|
|
5
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
6
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
7
|
-
if (!frame) throw new Error('Frame not found');
|
|
8
|
-
await frame.waitForSelector('body', { timeout: 30000, state: 'attached' });
|
|
9
|
-
await page.waitForTimeout(1000); // Give time for Vue components to mount
|
|
10
|
-
return frame;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
test('renders default button', async ({ page }) => {
|
|
14
|
-
await page.goto('http://localhost:7000/?path=/story/wl-button--default');
|
|
15
|
-
const frame = await getFrame(page);
|
|
16
|
-
|
|
17
|
-
const button = frame.locator('button.v-btn:visible').first();
|
|
18
|
-
await expect(button).toBeVisible();
|
|
19
|
-
await expect(button).toHaveText('Button');
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
test('can be clicked', async ({ page }) => {
|
|
23
|
-
await page.goto('http://localhost:7000/?path=/story/wl-button--default');
|
|
24
|
-
const frame = await getFrame(page);
|
|
25
|
-
|
|
26
|
-
const button = frame.locator('button.v-btn:visible').first();
|
|
27
|
-
await button.click();
|
|
28
|
-
await expect(button).toBeVisible();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('displays prepend icon', async ({ page }) => {
|
|
32
|
-
await page.goto('http://localhost:7000/?path=/story/wl-button--with-prepend-icon');
|
|
33
|
-
const frame = await getFrame(page);
|
|
34
|
-
|
|
35
|
-
const button = frame.locator('button.v-btn:visible').first();
|
|
36
|
-
await expect(button).toBeVisible();
|
|
37
|
-
const icon = button.locator('i').first();
|
|
38
|
-
await expect(icon).toBeVisible();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('shows loading state', async ({ page }) => {
|
|
42
|
-
await page.goto('http://localhost:7000/?path=/story/wl-button--loading-state');
|
|
43
|
-
const frame = await getFrame(page);
|
|
44
|
-
|
|
45
|
-
const button = frame.locator('button.v-btn:visible').first();
|
|
46
|
-
await expect(button).toBeVisible();
|
|
47
|
-
await expect(button).toHaveText('Loading...');
|
|
48
|
-
|
|
49
|
-
const loadingSpinner = frame.locator('.v-progress-circular').first();
|
|
50
|
-
await expect(loadingSpinner).toBeVisible();
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test('displays custom color', async ({ page }) => {
|
|
54
|
-
await page.goto('http://localhost:7000/?path=/story/wl-button--custom-color');
|
|
55
|
-
const frame = await getFrame(page);
|
|
56
|
-
|
|
57
|
-
const button = frame.locator('button.v-btn:visible').first();
|
|
58
|
-
await expect(button).toBeVisible();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
test('handles different sizes', async ({ page }) => {
|
|
62
|
-
await page.goto('http://localhost:7000/?path=/story/wl-button--small-button');
|
|
63
|
-
const frame = await getFrame(page);
|
|
64
|
-
|
|
65
|
-
const button = frame.locator('button.v-btn:visible').first();
|
|
66
|
-
await expect(button).toBeVisible();
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
test('supports different variants', async ({ page }) => {
|
|
70
|
-
await page.goto('http://localhost:7000/?path=/story/wl-button--outlined-variant');
|
|
71
|
-
const frame = await getFrame(page);
|
|
72
|
-
|
|
73
|
-
const button = frame.locator('button.v-btn:visible').first();
|
|
74
|
-
await expect(button).toBeVisible();
|
|
75
|
-
});
|
|
76
|
-
});
|
|
1
|
+
import { test, expect } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
test.describe('Button Component', () => {
|
|
4
|
+
async function getFrame(page) {
|
|
5
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
6
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
7
|
+
if (!frame) throw new Error('Frame not found');
|
|
8
|
+
await frame.waitForSelector('body', { timeout: 30000, state: 'attached' });
|
|
9
|
+
await page.waitForTimeout(1000); // Give time for Vue components to mount
|
|
10
|
+
return frame;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
test('renders default button', async ({ page }) => {
|
|
14
|
+
await page.goto('http://localhost:7000/?path=/story/wl-button--default');
|
|
15
|
+
const frame = await getFrame(page);
|
|
16
|
+
|
|
17
|
+
const button = frame.locator('button.v-btn:visible').first();
|
|
18
|
+
await expect(button).toBeVisible();
|
|
19
|
+
await expect(button).toHaveText('Button');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('can be clicked', async ({ page }) => {
|
|
23
|
+
await page.goto('http://localhost:7000/?path=/story/wl-button--default');
|
|
24
|
+
const frame = await getFrame(page);
|
|
25
|
+
|
|
26
|
+
const button = frame.locator('button.v-btn:visible').first();
|
|
27
|
+
await button.click();
|
|
28
|
+
await expect(button).toBeVisible();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('displays prepend icon', async ({ page }) => {
|
|
32
|
+
await page.goto('http://localhost:7000/?path=/story/wl-button--with-prepend-icon');
|
|
33
|
+
const frame = await getFrame(page);
|
|
34
|
+
|
|
35
|
+
const button = frame.locator('button.v-btn:visible').first();
|
|
36
|
+
await expect(button).toBeVisible();
|
|
37
|
+
const icon = button.locator('i').first();
|
|
38
|
+
await expect(icon).toBeVisible();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('shows loading state', async ({ page }) => {
|
|
42
|
+
await page.goto('http://localhost:7000/?path=/story/wl-button--loading-state');
|
|
43
|
+
const frame = await getFrame(page);
|
|
44
|
+
|
|
45
|
+
const button = frame.locator('button.v-btn:visible').first();
|
|
46
|
+
await expect(button).toBeVisible();
|
|
47
|
+
await expect(button).toHaveText('Loading...');
|
|
48
|
+
|
|
49
|
+
const loadingSpinner = frame.locator('.v-progress-circular').first();
|
|
50
|
+
await expect(loadingSpinner).toBeVisible();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('displays custom color', async ({ page }) => {
|
|
54
|
+
await page.goto('http://localhost:7000/?path=/story/wl-button--custom-color');
|
|
55
|
+
const frame = await getFrame(page);
|
|
56
|
+
|
|
57
|
+
const button = frame.locator('button.v-btn:visible').first();
|
|
58
|
+
await expect(button).toBeVisible();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('handles different sizes', async ({ page }) => {
|
|
62
|
+
await page.goto('http://localhost:7000/?path=/story/wl-button--small-button');
|
|
63
|
+
const frame = await getFrame(page);
|
|
64
|
+
|
|
65
|
+
const button = frame.locator('button.v-btn:visible').first();
|
|
66
|
+
await expect(button).toBeVisible();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('supports different variants', async ({ page }) => {
|
|
70
|
+
await page.goto('http://localhost:7000/?path=/story/wl-button--outlined-variant');
|
|
71
|
+
const frame = await getFrame(page);
|
|
72
|
+
|
|
73
|
+
const button = frame.locator('button.v-btn:visible').first();
|
|
74
|
+
await expect(button).toBeVisible();
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import { test, expect } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
test.describe('Checkbox Component', () => {
|
|
4
|
-
async function getFrame(page) {
|
|
5
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
6
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
7
|
-
if (!frame) throw new Error('Frame not found');
|
|
8
|
-
await frame.waitForSelector('body', { timeout: 30000, state: 'attached' });
|
|
9
|
-
await page.waitForTimeout(1000); // Give time for Vue components to mount
|
|
10
|
-
return frame;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
test('renders default checkbox', async ({ page }) => {
|
|
14
|
-
await page.goto('http://localhost:7000/?path=/story/wl-checkbox--default');
|
|
15
|
-
const frame = await getFrame(page);
|
|
16
|
-
|
|
17
|
-
const checkbox = frame.locator('input[type="checkbox"]').first();
|
|
18
|
-
await expect(checkbox).toBeAttached();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test('can be checked and unchecked', async ({ page }) => {
|
|
22
|
-
await page.goto('http://localhost:7000/?path=/story/wl-checkbox--default');
|
|
23
|
-
const frame = await getFrame(page);
|
|
24
|
-
|
|
25
|
-
const input = frame.locator('input[type="checkbox"]').first();
|
|
26
|
-
const label = frame.locator('label').first();
|
|
27
|
-
|
|
28
|
-
await label.click();
|
|
29
|
-
await expect(input).toBeChecked();
|
|
30
|
-
|
|
31
|
-
await label.click();
|
|
32
|
-
await expect(input).not.toBeChecked();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test('displays label', async ({ page }) => {
|
|
36
|
-
await page.goto('http://localhost:7000/?path=/story/wl-checkbox--default');
|
|
37
|
-
const frame = await getFrame(page);
|
|
38
|
-
|
|
39
|
-
const label = frame.locator('label').first();
|
|
40
|
-
await expect(label).toBeVisible();
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('handles disabled state', async ({ page }) => {
|
|
44
|
-
await page.goto('http://localhost:7000/?path=/story/wl-checkbox--disabled');
|
|
45
|
-
const frame = await getFrame(page);
|
|
46
|
-
|
|
47
|
-
const input = frame.locator('input[type="checkbox"]').first();
|
|
48
|
-
await expect(input).toBeDisabled();
|
|
49
|
-
});
|
|
50
|
-
});
|
|
1
|
+
import { test, expect } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
test.describe('Checkbox Component', () => {
|
|
4
|
+
async function getFrame(page) {
|
|
5
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
6
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
7
|
+
if (!frame) throw new Error('Frame not found');
|
|
8
|
+
await frame.waitForSelector('body', { timeout: 30000, state: 'attached' });
|
|
9
|
+
await page.waitForTimeout(1000); // Give time for Vue components to mount
|
|
10
|
+
return frame;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
test('renders default checkbox', async ({ page }) => {
|
|
14
|
+
await page.goto('http://localhost:7000/?path=/story/wl-checkbox--default');
|
|
15
|
+
const frame = await getFrame(page);
|
|
16
|
+
|
|
17
|
+
const checkbox = frame.locator('input[type="checkbox"]').first();
|
|
18
|
+
await expect(checkbox).toBeAttached();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('can be checked and unchecked', async ({ page }) => {
|
|
22
|
+
await page.goto('http://localhost:7000/?path=/story/wl-checkbox--default');
|
|
23
|
+
const frame = await getFrame(page);
|
|
24
|
+
|
|
25
|
+
const input = frame.locator('input[type="checkbox"]').first();
|
|
26
|
+
const label = frame.locator('label').first();
|
|
27
|
+
|
|
28
|
+
await label.click();
|
|
29
|
+
await expect(input).toBeChecked();
|
|
30
|
+
|
|
31
|
+
await label.click();
|
|
32
|
+
await expect(input).not.toBeChecked();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('displays label', async ({ page }) => {
|
|
36
|
+
await page.goto('http://localhost:7000/?path=/story/wl-checkbox--default');
|
|
37
|
+
const frame = await getFrame(page);
|
|
38
|
+
|
|
39
|
+
const label = frame.locator('label').first();
|
|
40
|
+
await expect(label).toBeVisible();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('handles disabled state', async ({ page }) => {
|
|
44
|
+
await page.goto('http://localhost:7000/?path=/story/wl-checkbox--disabled');
|
|
45
|
+
const frame = await getFrame(page);
|
|
46
|
+
|
|
47
|
+
const input = frame.locator('input[type="checkbox"]').first();
|
|
48
|
+
await expect(input).toBeDisabled();
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import { test, expect } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
test.describe('DateInput Component', () => {
|
|
4
|
-
async function getFrame(page) {
|
|
5
|
-
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
6
|
-
const frame = page.frame({ url: /iframe\.html/ });
|
|
7
|
-
if (!frame) throw new Error('Frame not found');
|
|
8
|
-
await frame.waitForSelector('body', { timeout: 30000, state: 'attached' });
|
|
9
|
-
await page.waitForTimeout(1000); // Give time for Vue components to mount
|
|
10
|
-
return frame;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
test('renders date input', async ({ page }) => {
|
|
14
|
-
await page.goto('http://localhost:7000/?path=/story/wl-dateinput--default');
|
|
15
|
-
const frame = await getFrame(page);
|
|
16
|
-
|
|
17
|
-
const dateInput = frame.locator('.v-text-field, input[type="date"], input[type="text"]').first();
|
|
18
|
-
await expect(dateInput).toBeVisible();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test('accepts date input', async ({ page }) => {
|
|
22
|
-
await page.goto('http://localhost:7000/?path=/story/wl-dateinput--default');
|
|
23
|
-
const frame = await getFrame(page);
|
|
24
|
-
|
|
25
|
-
const input = frame.locator('input').first();
|
|
26
|
-
await input.fill('2024-01-01');
|
|
27
|
-
await expect(input).toHaveValue(/2024|01/);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test('opens date picker on icon click', async ({ page }) => {
|
|
31
|
-
await page.goto('http://localhost:7000/?path=/story/wl-dateinput--default');
|
|
32
|
-
const frame = await getFrame(page);
|
|
33
|
-
|
|
34
|
-
// Click on the native date input that overlays the icon
|
|
35
|
-
const nativeDateInput = frame.locator('input[type="date"].native-date').first();
|
|
36
|
-
if (await nativeDateInput.count() > 0) {
|
|
37
|
-
await nativeDateInput.click({ force: true });
|
|
38
|
-
// Native date picker behavior is browser-specific, so we just verify the input exists
|
|
39
|
-
await expect(nativeDateInput).toBeAttached();
|
|
40
|
-
} else {
|
|
41
|
-
// Fallback: check that the date wrapper exists
|
|
42
|
-
const dateWrapper = frame.locator('.date-wrapper').first();
|
|
43
|
-
await expect(dateWrapper).toBeVisible();
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
});
|
|
1
|
+
import { test, expect } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
test.describe('DateInput Component', () => {
|
|
4
|
+
async function getFrame(page) {
|
|
5
|
+
await page.waitForSelector('#storybook-preview-iframe', { timeout: 30000 });
|
|
6
|
+
const frame = page.frame({ url: /iframe\.html/ });
|
|
7
|
+
if (!frame) throw new Error('Frame not found');
|
|
8
|
+
await frame.waitForSelector('body', { timeout: 30000, state: 'attached' });
|
|
9
|
+
await page.waitForTimeout(1000); // Give time for Vue components to mount
|
|
10
|
+
return frame;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
test('renders date input', async ({ page }) => {
|
|
14
|
+
await page.goto('http://localhost:7000/?path=/story/wl-dateinput--default');
|
|
15
|
+
const frame = await getFrame(page);
|
|
16
|
+
|
|
17
|
+
const dateInput = frame.locator('.v-text-field, input[type="date"], input[type="text"]').first();
|
|
18
|
+
await expect(dateInput).toBeVisible();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('accepts date input', async ({ page }) => {
|
|
22
|
+
await page.goto('http://localhost:7000/?path=/story/wl-dateinput--default');
|
|
23
|
+
const frame = await getFrame(page);
|
|
24
|
+
|
|
25
|
+
const input = frame.locator('input').first();
|
|
26
|
+
await input.fill('2024-01-01');
|
|
27
|
+
await expect(input).toHaveValue(/2024|01/);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('opens date picker on icon click', async ({ page }) => {
|
|
31
|
+
await page.goto('http://localhost:7000/?path=/story/wl-dateinput--default');
|
|
32
|
+
const frame = await getFrame(page);
|
|
33
|
+
|
|
34
|
+
// Click on the native date input that overlays the icon
|
|
35
|
+
const nativeDateInput = frame.locator('input[type="date"].native-date').first();
|
|
36
|
+
if (await nativeDateInput.count() > 0) {
|
|
37
|
+
await nativeDateInput.click({ force: true });
|
|
38
|
+
// Native date picker behavior is browser-specific, so we just verify the input exists
|
|
39
|
+
await expect(nativeDateInput).toBeAttached();
|
|
40
|
+
} else {
|
|
41
|
+
// Fallback: check that the date wrapper exists
|
|
42
|
+
const dateWrapper = frame.locator('.date-wrapper').first();
|
|
43
|
+
await expect(dateWrapper).toBeVisible();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
});
|
package/tests/e2e/debug.spec.ts
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
import { test, expect } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
test.describe('Debug DOM Structure', () => {
|
|
4
|
-
test('inspect Storybook DOM structure', async ({ page }) => {
|
|
5
|
-
await page.goto('http://localhost:7000/?path=/story/wl-button--default');
|
|
6
|
-
|
|
7
|
-
// Wait for page load
|
|
8
|
-
await page.waitForLoadState('networkidle');
|
|
9
|
-
|
|
10
|
-
// Check what's actually in the DOM
|
|
11
|
-
const bodyContent = await page.locator('body').innerHTML();
|
|
12
|
-
console.log('Body HTML:', bodyContent.substring(0, 1000));
|
|
13
|
-
|
|
14
|
-
// Look for common Storybook selectors
|
|
15
|
-
const possibleSelectors = [
|
|
16
|
-
'#storybook-root',
|
|
17
|
-
'#root',
|
|
18
|
-
'.sb-main-padded',
|
|
19
|
-
'.docs-story',
|
|
20
|
-
'#story--wl-button--default',
|
|
21
|
-
'[data-testid]',
|
|
22
|
-
'.sb-show-main',
|
|
23
|
-
'#storybook-preview-iframe'
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
for (const selector of possibleSelectors) {
|
|
27
|
-
const exists = await page.locator(selector).count();
|
|
28
|
-
console.log(`${selector}: ${exists > 0 ? 'EXISTS' : 'NOT FOUND'} (${exists} elements)`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Check if we're in an iframe
|
|
32
|
-
const frames = page.frames();
|
|
33
|
-
console.log(`Number of frames: ${frames.length}`);
|
|
34
|
-
|
|
35
|
-
for (let i = 0; i < frames.length; i++) {
|
|
36
|
-
const frame = frames[i];
|
|
37
|
-
const frameUrl = frame.url();
|
|
38
|
-
console.log(`Frame ${i}: ${frameUrl}`);
|
|
39
|
-
|
|
40
|
-
if (frameUrl.includes('iframe.html')) {
|
|
41
|
-
console.log('Found iframe frame!');
|
|
42
|
-
|
|
43
|
-
// Check content inside iframe
|
|
44
|
-
const iframeContent = await frame.locator('body').count();
|
|
45
|
-
console.log(`Iframe body elements: ${iframeContent}`);
|
|
46
|
-
|
|
47
|
-
const button = await frame.locator('button').count();
|
|
48
|
-
console.log(`Buttons in iframe: ${button}`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
});
|
|
1
|
+
import { test, expect } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
test.describe('Debug DOM Structure', () => {
|
|
4
|
+
test('inspect Storybook DOM structure', async ({ page }) => {
|
|
5
|
+
await page.goto('http://localhost:7000/?path=/story/wl-button--default');
|
|
6
|
+
|
|
7
|
+
// Wait for page load
|
|
8
|
+
await page.waitForLoadState('networkidle');
|
|
9
|
+
|
|
10
|
+
// Check what's actually in the DOM
|
|
11
|
+
const bodyContent = await page.locator('body').innerHTML();
|
|
12
|
+
console.log('Body HTML:', bodyContent.substring(0, 1000));
|
|
13
|
+
|
|
14
|
+
// Look for common Storybook selectors
|
|
15
|
+
const possibleSelectors = [
|
|
16
|
+
'#storybook-root',
|
|
17
|
+
'#root',
|
|
18
|
+
'.sb-main-padded',
|
|
19
|
+
'.docs-story',
|
|
20
|
+
'#story--wl-button--default',
|
|
21
|
+
'[data-testid]',
|
|
22
|
+
'.sb-show-main',
|
|
23
|
+
'#storybook-preview-iframe'
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
for (const selector of possibleSelectors) {
|
|
27
|
+
const exists = await page.locator(selector).count();
|
|
28
|
+
console.log(`${selector}: ${exists > 0 ? 'EXISTS' : 'NOT FOUND'} (${exists} elements)`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Check if we're in an iframe
|
|
32
|
+
const frames = page.frames();
|
|
33
|
+
console.log(`Number of frames: ${frames.length}`);
|
|
34
|
+
|
|
35
|
+
for (let i = 0; i < frames.length; i++) {
|
|
36
|
+
const frame = frames[i];
|
|
37
|
+
const frameUrl = frame.url();
|
|
38
|
+
console.log(`Frame ${i}: ${frameUrl}`);
|
|
39
|
+
|
|
40
|
+
if (frameUrl.includes('iframe.html')) {
|
|
41
|
+
console.log('Found iframe frame!');
|
|
42
|
+
|
|
43
|
+
// Check content inside iframe
|
|
44
|
+
const iframeContent = await frame.locator('body').count();
|
|
45
|
+
console.log(`Iframe body elements: ${iframeContent}`);
|
|
46
|
+
|
|
47
|
+
const button = await frame.locator('button').count();
|
|
48
|
+
console.log(`Buttons in iframe: ${button}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
52
|
});
|