@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,486 +1,486 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { mount } from '@vue/test-utils';
|
|
3
|
-
import Dialog from '@components/Dialog/Dialog.vue';
|
|
4
|
-
|
|
5
|
-
// Mock console.log to avoid cluttering test output
|
|
6
|
-
vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
7
|
-
|
|
8
|
-
describe('Dialog', () => {
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
vi.clearAllMocks();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
// Test default behavior and rendering
|
|
14
|
-
describe('Default Behavior', () => {
|
|
15
|
-
it('renders with default state', () => {
|
|
16
|
-
const wrapper = mount(Dialog);
|
|
17
|
-
|
|
18
|
-
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
19
|
-
expect(wrapper.find('[data-testid="v-dialog"]').exists()).toBe(true);
|
|
20
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('applies correct CSS classes', () => {
|
|
24
|
-
const wrapper = mount(Dialog);
|
|
25
|
-
|
|
26
|
-
expect(wrapper.find('.text-center').exists()).toBe(true);
|
|
27
|
-
expect(wrapper.find('.pa-4').exists()).toBe(true);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('initializes dialog state as closed', () => {
|
|
31
|
-
const wrapper = mount(Dialog);
|
|
32
|
-
|
|
33
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// Test dialog state management
|
|
38
|
-
describe('Dialog State Management', () => {
|
|
39
|
-
it('opens dialog when openDialog is called', () => {
|
|
40
|
-
const wrapper = mount(Dialog);
|
|
41
|
-
|
|
42
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
43
|
-
|
|
44
|
-
wrapper.vm.openDialog();
|
|
45
|
-
|
|
46
|
-
expect(wrapper.vm.dialog).toBe(true);
|
|
47
|
-
expect(console.log).toHaveBeenCalledWith('entereed 1');
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('closes dialog when closeDialog is called', () => {
|
|
51
|
-
const wrapper = mount(Dialog);
|
|
52
|
-
|
|
53
|
-
// First open the dialog
|
|
54
|
-
wrapper.vm.openDialog();
|
|
55
|
-
expect(wrapper.vm.dialog).toBe(true);
|
|
56
|
-
|
|
57
|
-
// Then close it
|
|
58
|
-
wrapper.vm.closeDialog();
|
|
59
|
-
|
|
60
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
61
|
-
expect(console.log).toHaveBeenCalledWith('entereed 2');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('can toggle dialog state multiple times', () => {
|
|
65
|
-
const wrapper = mount(Dialog);
|
|
66
|
-
|
|
67
|
-
// Initial state
|
|
68
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
69
|
-
|
|
70
|
-
// Open -> Close -> Open -> Close
|
|
71
|
-
wrapper.vm.openDialog();
|
|
72
|
-
expect(wrapper.vm.dialog).toBe(true);
|
|
73
|
-
|
|
74
|
-
wrapper.vm.closeDialog();
|
|
75
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
76
|
-
|
|
77
|
-
wrapper.vm.openDialog();
|
|
78
|
-
expect(wrapper.vm.dialog).toBe(true);
|
|
79
|
-
|
|
80
|
-
wrapper.vm.closeDialog();
|
|
81
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// Test v-model binding
|
|
86
|
-
describe('v-model Binding', () => {
|
|
87
|
-
it('binds dialog state to v-dialog model', async () => {
|
|
88
|
-
const wrapper = mount(Dialog);
|
|
89
|
-
|
|
90
|
-
// Initially closed
|
|
91
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
92
|
-
|
|
93
|
-
// Open dialog
|
|
94
|
-
wrapper.vm.openDialog();
|
|
95
|
-
await wrapper.vm.$nextTick();
|
|
96
|
-
|
|
97
|
-
expect(wrapper.vm.dialog).toBe(true);
|
|
98
|
-
// The v-dialog component should receive the updated model value
|
|
99
|
-
expect(wrapper.find('[data-testid="v-dialog"]').exists()).toBe(true);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('updates when dialog reactive ref changes', async () => {
|
|
103
|
-
const wrapper = mount(Dialog);
|
|
104
|
-
|
|
105
|
-
// Directly modify the reactive ref
|
|
106
|
-
wrapper.vm.dialog = true;
|
|
107
|
-
await wrapper.vm.$nextTick();
|
|
108
|
-
|
|
109
|
-
expect(wrapper.vm.dialog).toBe(true);
|
|
110
|
-
|
|
111
|
-
wrapper.vm.dialog = false;
|
|
112
|
-
await wrapper.vm.$nextTick();
|
|
113
|
-
|
|
114
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// Test slots
|
|
119
|
-
describe('Slots', () => {
|
|
120
|
-
it('renders activator slot with openDialog prop', () => {
|
|
121
|
-
const wrapper = mount(Dialog, {
|
|
122
|
-
slots: {
|
|
123
|
-
activator: `
|
|
124
|
-
<template #activator="{ openDialog }">
|
|
125
|
-
<button @click="openDialog" data-testid="activator-button">
|
|
126
|
-
Open Dialog
|
|
127
|
-
</button>
|
|
128
|
-
</template>
|
|
129
|
-
`
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
const activatorButton = wrapper.find('[data-testid="activator-button"]');
|
|
134
|
-
expect(activatorButton.exists()).toBe(true);
|
|
135
|
-
expect(activatorButton.text()).toBe('Open Dialog');
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it('renders content slot with closeDialog prop', () => {
|
|
139
|
-
const wrapper = mount(Dialog, {
|
|
140
|
-
slots: {
|
|
141
|
-
content: `
|
|
142
|
-
<template #content="{ closeDialog }">
|
|
143
|
-
<div data-testid="dialog-content">
|
|
144
|
-
<h1>Dialog Content</h1>
|
|
145
|
-
<button @click="closeDialog" data-testid="close-button">
|
|
146
|
-
Close
|
|
147
|
-
</button>
|
|
148
|
-
</div>
|
|
149
|
-
</template>
|
|
150
|
-
`
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
const dialogContent = wrapper.find('[data-testid="dialog-content"]');
|
|
155
|
-
expect(dialogContent.exists()).toBe(true);
|
|
156
|
-
expect(dialogContent.text()).toContain('Dialog Content');
|
|
157
|
-
|
|
158
|
-
const closeButton = wrapper.find('[data-testid="close-button"]');
|
|
159
|
-
expect(closeButton.exists()).toBe(true);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it('renders both activator and content slots together', () => {
|
|
163
|
-
const wrapper = mount(Dialog, {
|
|
164
|
-
slots: {
|
|
165
|
-
activator: `
|
|
166
|
-
<template #activator="{ openDialog }">
|
|
167
|
-
<button @click="openDialog" data-testid="activator">
|
|
168
|
-
Open
|
|
169
|
-
</button>
|
|
170
|
-
</template>
|
|
171
|
-
`,
|
|
172
|
-
content: `
|
|
173
|
-
<template #content="{ closeDialog }">
|
|
174
|
-
<div data-testid="content">
|
|
175
|
-
<span>Content</span>
|
|
176
|
-
<button @click="closeDialog" data-testid="close">
|
|
177
|
-
Close
|
|
178
|
-
</button>
|
|
179
|
-
</div>
|
|
180
|
-
</template>
|
|
181
|
-
`
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
expect(wrapper.find('[data-testid="activator"]').exists()).toBe(true);
|
|
186
|
-
expect(wrapper.find('[data-testid="content"]').exists()).toBe(true);
|
|
187
|
-
expect(wrapper.find('[data-testid="close"]').exists()).toBe(true);
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
// Test slot prop functionality
|
|
192
|
-
describe('Slot Prop Functionality', () => {
|
|
193
|
-
it('openDialog slot prop opens the dialog', async () => {
|
|
194
|
-
const wrapper = mount(Dialog, {
|
|
195
|
-
slots: {
|
|
196
|
-
activator: `
|
|
197
|
-
<template #activator="{ openDialog }">
|
|
198
|
-
<button @click="openDialog" data-testid="open-btn">
|
|
199
|
-
Open
|
|
200
|
-
</button>
|
|
201
|
-
</template>
|
|
202
|
-
`
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
207
|
-
|
|
208
|
-
const openButton = wrapper.find('[data-testid="open-btn"]');
|
|
209
|
-
await openButton.trigger('click');
|
|
210
|
-
|
|
211
|
-
expect(wrapper.vm.dialog).toBe(true);
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it('closeDialog slot prop closes the dialog', async () => {
|
|
215
|
-
const wrapper = mount(Dialog, {
|
|
216
|
-
slots: {
|
|
217
|
-
content: `
|
|
218
|
-
<template #content="{ closeDialog }">
|
|
219
|
-
<button @click="closeDialog" data-testid="close-btn">
|
|
220
|
-
Close
|
|
221
|
-
</button>
|
|
222
|
-
</template>
|
|
223
|
-
`
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
// First open the dialog
|
|
228
|
-
wrapper.vm.openDialog();
|
|
229
|
-
expect(wrapper.vm.dialog).toBe(true);
|
|
230
|
-
|
|
231
|
-
const closeButton = wrapper.find('[data-testid="close-btn"]');
|
|
232
|
-
await closeButton.trigger('click');
|
|
233
|
-
|
|
234
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
// Test Vuetify integration
|
|
239
|
-
describe('Vuetify Integration', () => {
|
|
240
|
-
it('passes width="auto" to v-dialog', () => {
|
|
241
|
-
const wrapper = mount(Dialog);
|
|
242
|
-
|
|
243
|
-
const vDialog = wrapper.find('[data-testid="v-dialog"]');
|
|
244
|
-
expect(vDialog.exists()).toBe(true);
|
|
245
|
-
// With stubbed components, we can't directly test Vuetify props
|
|
246
|
-
// but we can verify the component renders correctly
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
it('properly binds v-model to v-dialog', async () => {
|
|
250
|
-
const wrapper = mount(Dialog);
|
|
251
|
-
|
|
252
|
-
// Initially false
|
|
253
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
254
|
-
|
|
255
|
-
// Open dialog
|
|
256
|
-
wrapper.vm.openDialog();
|
|
257
|
-
await wrapper.vm.$nextTick();
|
|
258
|
-
|
|
259
|
-
// Verify binding
|
|
260
|
-
expect(wrapper.vm.dialog).toBe(true);
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
// Test accessibility
|
|
265
|
-
describe('Accessibility', () => {
|
|
266
|
-
it('has data-testid for testing', () => {
|
|
267
|
-
const wrapper = mount(Dialog);
|
|
268
|
-
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it('provides accessible activator pattern', () => {
|
|
272
|
-
const wrapper = mount(Dialog, {
|
|
273
|
-
slots: {
|
|
274
|
-
activator: `
|
|
275
|
-
<template #activator="{ openDialog }">
|
|
276
|
-
<button @click="openDialog" aria-label="Open dialog">
|
|
277
|
-
Open
|
|
278
|
-
</button>
|
|
279
|
-
</template>
|
|
280
|
-
`
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
const button = wrapper.find('button');
|
|
285
|
-
expect(button.exists()).toBe(true);
|
|
286
|
-
expect(button.attributes('aria-label')).toBe('Open dialog');
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
it('supports keyboard interactions through slots', () => {
|
|
290
|
-
const wrapper = mount(Dialog, {
|
|
291
|
-
slots: {
|
|
292
|
-
activator: `
|
|
293
|
-
<template #activator="{ openDialog }">
|
|
294
|
-
<button @click="openDialog" @keydown.enter="openDialog">
|
|
295
|
-
Open
|
|
296
|
-
</button>
|
|
297
|
-
</template>
|
|
298
|
-
`,
|
|
299
|
-
content: `
|
|
300
|
-
<template #content="{ closeDialog }">
|
|
301
|
-
<button @click="closeDialog" @keydown.escape="closeDialog">
|
|
302
|
-
Close
|
|
303
|
-
</button>
|
|
304
|
-
</template>
|
|
305
|
-
`
|
|
306
|
-
}
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
expect(wrapper.find('button').exists()).toBe(true);
|
|
310
|
-
});
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
// Test console logging
|
|
314
|
-
describe('Console Logging', () => {
|
|
315
|
-
it('logs when opening dialog', () => {
|
|
316
|
-
const wrapper = mount(Dialog);
|
|
317
|
-
|
|
318
|
-
wrapper.vm.openDialog();
|
|
319
|
-
|
|
320
|
-
expect(console.log).toHaveBeenCalledWith('entereed 1');
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
it('logs when closing dialog', () => {
|
|
324
|
-
const wrapper = mount(Dialog);
|
|
325
|
-
|
|
326
|
-
wrapper.vm.closeDialog();
|
|
327
|
-
|
|
328
|
-
expect(console.log).toHaveBeenCalledWith('entereed 2');
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
it('logs multiple times for multiple operations', () => {
|
|
332
|
-
const wrapper = mount(Dialog);
|
|
333
|
-
|
|
334
|
-
wrapper.vm.openDialog();
|
|
335
|
-
wrapper.vm.closeDialog();
|
|
336
|
-
wrapper.vm.openDialog();
|
|
337
|
-
|
|
338
|
-
expect(console.log).toHaveBeenCalledTimes(3);
|
|
339
|
-
expect(console.log).toHaveBeenNthCalledWith(1, 'entereed 1');
|
|
340
|
-
expect(console.log).toHaveBeenNthCalledWith(2, 'entereed 2');
|
|
341
|
-
expect(console.log).toHaveBeenNthCalledWith(3, 'entereed 1');
|
|
342
|
-
});
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
// Test edge cases
|
|
346
|
-
describe('Edge Cases', () => {
|
|
347
|
-
it('handles empty activator slot', () => {
|
|
348
|
-
const wrapper = mount(Dialog, {
|
|
349
|
-
slots: {
|
|
350
|
-
activator: ''
|
|
351
|
-
}
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
355
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
it('handles empty content slot', () => {
|
|
359
|
-
const wrapper = mount(Dialog, {
|
|
360
|
-
slots: {
|
|
361
|
-
content: ''
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
expect(wrapper.find('[data-testid="v-dialog"]').exists()).toBe(true);
|
|
366
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
it('handles no slots provided', () => {
|
|
370
|
-
const wrapper = mount(Dialog);
|
|
371
|
-
|
|
372
|
-
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
373
|
-
expect(wrapper.find('[data-testid="v-dialog"]').exists()).toBe(true);
|
|
374
|
-
expect(wrapper.vm.dialog).toBe(false);
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
it('handles rapid open/close calls', () => {
|
|
378
|
-
const wrapper = mount(Dialog);
|
|
379
|
-
|
|
380
|
-
// Rapid calls
|
|
381
|
-
wrapper.vm.openDialog();
|
|
382
|
-
wrapper.vm.closeDialog();
|
|
383
|
-
wrapper.vm.openDialog();
|
|
384
|
-
wrapper.vm.closeDialog();
|
|
385
|
-
wrapper.vm.openDialog();
|
|
386
|
-
|
|
387
|
-
expect(wrapper.vm.dialog).toBe(true);
|
|
388
|
-
expect(console.log).toHaveBeenCalledTimes(5);
|
|
389
|
-
});
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
// Test complex slot scenarios
|
|
393
|
-
describe('Complex Slot Scenarios', () => {
|
|
394
|
-
it('supports complex activator with multiple elements', () => {
|
|
395
|
-
const wrapper = mount(Dialog, {
|
|
396
|
-
slots: {
|
|
397
|
-
activator: `
|
|
398
|
-
<template #activator="{ openDialog }">
|
|
399
|
-
<div class="activator-container">
|
|
400
|
-
<button @click="openDialog" data-testid="primary-button">
|
|
401
|
-
Primary Open
|
|
402
|
-
</button>
|
|
403
|
-
<button @click="openDialog" data-testid="secondary-button">
|
|
404
|
-
Secondary Open
|
|
405
|
-
</button>
|
|
406
|
-
</div>
|
|
407
|
-
</template>
|
|
408
|
-
`
|
|
409
|
-
}
|
|
410
|
-
});
|
|
411
|
-
|
|
412
|
-
expect(wrapper.find('.activator-container').exists()).toBe(true);
|
|
413
|
-
expect(wrapper.find('[data-testid="primary-button"]').exists()).toBe(true);
|
|
414
|
-
expect(wrapper.find('[data-testid="secondary-button"]').exists()).toBe(true);
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
it('supports complex content with multiple interaction elements', () => {
|
|
418
|
-
const wrapper = mount(Dialog, {
|
|
419
|
-
slots: {
|
|
420
|
-
content: `
|
|
421
|
-
<template #content="{ closeDialog }">
|
|
422
|
-
<div class="dialog-content">
|
|
423
|
-
<header>
|
|
424
|
-
<h1>Dialog Title</h1>
|
|
425
|
-
<button @click="closeDialog" data-testid="header-close">×</button>
|
|
426
|
-
</header>
|
|
427
|
-
<main>
|
|
428
|
-
<p>Dialog content goes here</p>
|
|
429
|
-
</main>
|
|
430
|
-
<footer>
|
|
431
|
-
<button @click="closeDialog" data-testid="cancel-button">
|
|
432
|
-
Cancel
|
|
433
|
-
</button>
|
|
434
|
-
<button @click="closeDialog" data-testid="confirm-button">
|
|
435
|
-
Confirm
|
|
436
|
-
</button>
|
|
437
|
-
</footer>
|
|
438
|
-
</div>
|
|
439
|
-
</template>
|
|
440
|
-
`
|
|
441
|
-
}
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
expect(wrapper.find('.dialog-content').exists()).toBe(true);
|
|
445
|
-
expect(wrapper.find('[data-testid="header-close"]').exists()).toBe(true);
|
|
446
|
-
expect(wrapper.find('[data-testid="cancel-button"]').exists()).toBe(true);
|
|
447
|
-
expect(wrapper.find('[data-testid="confirm-button"]').exists()).toBe(true);
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
it('handles nested components in slots', () => {
|
|
451
|
-
const wrapper = mount(Dialog, {
|
|
452
|
-
slots: {
|
|
453
|
-
activator: `
|
|
454
|
-
<template #activator="{ openDialog }">
|
|
455
|
-
<div class="nested-component">
|
|
456
|
-
<span>Click to open:</span>
|
|
457
|
-
<button @click="openDialog">Open Dialog</button>
|
|
458
|
-
</div>
|
|
459
|
-
</template>
|
|
460
|
-
`,
|
|
461
|
-
content: `
|
|
462
|
-
<template #content="{ closeDialog }">
|
|
463
|
-
<div class="modal-wrapper">
|
|
464
|
-
<div class="modal-header">
|
|
465
|
-
<h2>Nested Modal</h2>
|
|
466
|
-
</div>
|
|
467
|
-
<div class="modal-body">
|
|
468
|
-
<p>This is a nested component structure</p>
|
|
469
|
-
</div>
|
|
470
|
-
<div class="modal-footer">
|
|
471
|
-
<button @click="closeDialog">Close</button>
|
|
472
|
-
</div>
|
|
473
|
-
</div>
|
|
474
|
-
</template>
|
|
475
|
-
`
|
|
476
|
-
}
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
expect(wrapper.find('.nested-component').exists()).toBe(true);
|
|
480
|
-
expect(wrapper.find('.modal-wrapper').exists()).toBe(true);
|
|
481
|
-
expect(wrapper.find('.modal-header').exists()).toBe(true);
|
|
482
|
-
expect(wrapper.find('.modal-body').exists()).toBe(true);
|
|
483
|
-
expect(wrapper.find('.modal-footer').exists()).toBe(true);
|
|
484
|
-
});
|
|
485
|
-
});
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import Dialog from '@components/Dialog/Dialog.vue';
|
|
4
|
+
|
|
5
|
+
// Mock console.log to avoid cluttering test output
|
|
6
|
+
vi.spyOn(console, 'log').mockImplementation(() => {});
|
|
7
|
+
|
|
8
|
+
describe('Dialog', () => {
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
vi.clearAllMocks();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// Test default behavior and rendering
|
|
14
|
+
describe('Default Behavior', () => {
|
|
15
|
+
it('renders with default state', () => {
|
|
16
|
+
const wrapper = mount(Dialog);
|
|
17
|
+
|
|
18
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
19
|
+
expect(wrapper.find('[data-testid="v-dialog"]').exists()).toBe(true);
|
|
20
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('applies correct CSS classes', () => {
|
|
24
|
+
const wrapper = mount(Dialog);
|
|
25
|
+
|
|
26
|
+
expect(wrapper.find('.text-center').exists()).toBe(true);
|
|
27
|
+
expect(wrapper.find('.pa-4').exists()).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('initializes dialog state as closed', () => {
|
|
31
|
+
const wrapper = mount(Dialog);
|
|
32
|
+
|
|
33
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Test dialog state management
|
|
38
|
+
describe('Dialog State Management', () => {
|
|
39
|
+
it('opens dialog when openDialog is called', () => {
|
|
40
|
+
const wrapper = mount(Dialog);
|
|
41
|
+
|
|
42
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
43
|
+
|
|
44
|
+
wrapper.vm.openDialog();
|
|
45
|
+
|
|
46
|
+
expect(wrapper.vm.dialog).toBe(true);
|
|
47
|
+
expect(console.log).toHaveBeenCalledWith('entereed 1');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('closes dialog when closeDialog is called', () => {
|
|
51
|
+
const wrapper = mount(Dialog);
|
|
52
|
+
|
|
53
|
+
// First open the dialog
|
|
54
|
+
wrapper.vm.openDialog();
|
|
55
|
+
expect(wrapper.vm.dialog).toBe(true);
|
|
56
|
+
|
|
57
|
+
// Then close it
|
|
58
|
+
wrapper.vm.closeDialog();
|
|
59
|
+
|
|
60
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
61
|
+
expect(console.log).toHaveBeenCalledWith('entereed 2');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('can toggle dialog state multiple times', () => {
|
|
65
|
+
const wrapper = mount(Dialog);
|
|
66
|
+
|
|
67
|
+
// Initial state
|
|
68
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
69
|
+
|
|
70
|
+
// Open -> Close -> Open -> Close
|
|
71
|
+
wrapper.vm.openDialog();
|
|
72
|
+
expect(wrapper.vm.dialog).toBe(true);
|
|
73
|
+
|
|
74
|
+
wrapper.vm.closeDialog();
|
|
75
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
76
|
+
|
|
77
|
+
wrapper.vm.openDialog();
|
|
78
|
+
expect(wrapper.vm.dialog).toBe(true);
|
|
79
|
+
|
|
80
|
+
wrapper.vm.closeDialog();
|
|
81
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Test v-model binding
|
|
86
|
+
describe('v-model Binding', () => {
|
|
87
|
+
it('binds dialog state to v-dialog model', async () => {
|
|
88
|
+
const wrapper = mount(Dialog);
|
|
89
|
+
|
|
90
|
+
// Initially closed
|
|
91
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
92
|
+
|
|
93
|
+
// Open dialog
|
|
94
|
+
wrapper.vm.openDialog();
|
|
95
|
+
await wrapper.vm.$nextTick();
|
|
96
|
+
|
|
97
|
+
expect(wrapper.vm.dialog).toBe(true);
|
|
98
|
+
// The v-dialog component should receive the updated model value
|
|
99
|
+
expect(wrapper.find('[data-testid="v-dialog"]').exists()).toBe(true);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('updates when dialog reactive ref changes', async () => {
|
|
103
|
+
const wrapper = mount(Dialog);
|
|
104
|
+
|
|
105
|
+
// Directly modify the reactive ref
|
|
106
|
+
wrapper.vm.dialog = true;
|
|
107
|
+
await wrapper.vm.$nextTick();
|
|
108
|
+
|
|
109
|
+
expect(wrapper.vm.dialog).toBe(true);
|
|
110
|
+
|
|
111
|
+
wrapper.vm.dialog = false;
|
|
112
|
+
await wrapper.vm.$nextTick();
|
|
113
|
+
|
|
114
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Test slots
|
|
119
|
+
describe('Slots', () => {
|
|
120
|
+
it('renders activator slot with openDialog prop', () => {
|
|
121
|
+
const wrapper = mount(Dialog, {
|
|
122
|
+
slots: {
|
|
123
|
+
activator: `
|
|
124
|
+
<template #activator="{ openDialog }">
|
|
125
|
+
<button @click="openDialog" data-testid="activator-button">
|
|
126
|
+
Open Dialog
|
|
127
|
+
</button>
|
|
128
|
+
</template>
|
|
129
|
+
`
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const activatorButton = wrapper.find('[data-testid="activator-button"]');
|
|
134
|
+
expect(activatorButton.exists()).toBe(true);
|
|
135
|
+
expect(activatorButton.text()).toBe('Open Dialog');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('renders content slot with closeDialog prop', () => {
|
|
139
|
+
const wrapper = mount(Dialog, {
|
|
140
|
+
slots: {
|
|
141
|
+
content: `
|
|
142
|
+
<template #content="{ closeDialog }">
|
|
143
|
+
<div data-testid="dialog-content">
|
|
144
|
+
<h1>Dialog Content</h1>
|
|
145
|
+
<button @click="closeDialog" data-testid="close-button">
|
|
146
|
+
Close
|
|
147
|
+
</button>
|
|
148
|
+
</div>
|
|
149
|
+
</template>
|
|
150
|
+
`
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const dialogContent = wrapper.find('[data-testid="dialog-content"]');
|
|
155
|
+
expect(dialogContent.exists()).toBe(true);
|
|
156
|
+
expect(dialogContent.text()).toContain('Dialog Content');
|
|
157
|
+
|
|
158
|
+
const closeButton = wrapper.find('[data-testid="close-button"]');
|
|
159
|
+
expect(closeButton.exists()).toBe(true);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('renders both activator and content slots together', () => {
|
|
163
|
+
const wrapper = mount(Dialog, {
|
|
164
|
+
slots: {
|
|
165
|
+
activator: `
|
|
166
|
+
<template #activator="{ openDialog }">
|
|
167
|
+
<button @click="openDialog" data-testid="activator">
|
|
168
|
+
Open
|
|
169
|
+
</button>
|
|
170
|
+
</template>
|
|
171
|
+
`,
|
|
172
|
+
content: `
|
|
173
|
+
<template #content="{ closeDialog }">
|
|
174
|
+
<div data-testid="content">
|
|
175
|
+
<span>Content</span>
|
|
176
|
+
<button @click="closeDialog" data-testid="close">
|
|
177
|
+
Close
|
|
178
|
+
</button>
|
|
179
|
+
</div>
|
|
180
|
+
</template>
|
|
181
|
+
`
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
expect(wrapper.find('[data-testid="activator"]').exists()).toBe(true);
|
|
186
|
+
expect(wrapper.find('[data-testid="content"]').exists()).toBe(true);
|
|
187
|
+
expect(wrapper.find('[data-testid="close"]').exists()).toBe(true);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Test slot prop functionality
|
|
192
|
+
describe('Slot Prop Functionality', () => {
|
|
193
|
+
it('openDialog slot prop opens the dialog', async () => {
|
|
194
|
+
const wrapper = mount(Dialog, {
|
|
195
|
+
slots: {
|
|
196
|
+
activator: `
|
|
197
|
+
<template #activator="{ openDialog }">
|
|
198
|
+
<button @click="openDialog" data-testid="open-btn">
|
|
199
|
+
Open
|
|
200
|
+
</button>
|
|
201
|
+
</template>
|
|
202
|
+
`
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
207
|
+
|
|
208
|
+
const openButton = wrapper.find('[data-testid="open-btn"]');
|
|
209
|
+
await openButton.trigger('click');
|
|
210
|
+
|
|
211
|
+
expect(wrapper.vm.dialog).toBe(true);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('closeDialog slot prop closes the dialog', async () => {
|
|
215
|
+
const wrapper = mount(Dialog, {
|
|
216
|
+
slots: {
|
|
217
|
+
content: `
|
|
218
|
+
<template #content="{ closeDialog }">
|
|
219
|
+
<button @click="closeDialog" data-testid="close-btn">
|
|
220
|
+
Close
|
|
221
|
+
</button>
|
|
222
|
+
</template>
|
|
223
|
+
`
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
// First open the dialog
|
|
228
|
+
wrapper.vm.openDialog();
|
|
229
|
+
expect(wrapper.vm.dialog).toBe(true);
|
|
230
|
+
|
|
231
|
+
const closeButton = wrapper.find('[data-testid="close-btn"]');
|
|
232
|
+
await closeButton.trigger('click');
|
|
233
|
+
|
|
234
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Test Vuetify integration
|
|
239
|
+
describe('Vuetify Integration', () => {
|
|
240
|
+
it('passes width="auto" to v-dialog', () => {
|
|
241
|
+
const wrapper = mount(Dialog);
|
|
242
|
+
|
|
243
|
+
const vDialog = wrapper.find('[data-testid="v-dialog"]');
|
|
244
|
+
expect(vDialog.exists()).toBe(true);
|
|
245
|
+
// With stubbed components, we can't directly test Vuetify props
|
|
246
|
+
// but we can verify the component renders correctly
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('properly binds v-model to v-dialog', async () => {
|
|
250
|
+
const wrapper = mount(Dialog);
|
|
251
|
+
|
|
252
|
+
// Initially false
|
|
253
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
254
|
+
|
|
255
|
+
// Open dialog
|
|
256
|
+
wrapper.vm.openDialog();
|
|
257
|
+
await wrapper.vm.$nextTick();
|
|
258
|
+
|
|
259
|
+
// Verify binding
|
|
260
|
+
expect(wrapper.vm.dialog).toBe(true);
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// Test accessibility
|
|
265
|
+
describe('Accessibility', () => {
|
|
266
|
+
it('has data-testid for testing', () => {
|
|
267
|
+
const wrapper = mount(Dialog);
|
|
268
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('provides accessible activator pattern', () => {
|
|
272
|
+
const wrapper = mount(Dialog, {
|
|
273
|
+
slots: {
|
|
274
|
+
activator: `
|
|
275
|
+
<template #activator="{ openDialog }">
|
|
276
|
+
<button @click="openDialog" aria-label="Open dialog">
|
|
277
|
+
Open
|
|
278
|
+
</button>
|
|
279
|
+
</template>
|
|
280
|
+
`
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const button = wrapper.find('button');
|
|
285
|
+
expect(button.exists()).toBe(true);
|
|
286
|
+
expect(button.attributes('aria-label')).toBe('Open dialog');
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('supports keyboard interactions through slots', () => {
|
|
290
|
+
const wrapper = mount(Dialog, {
|
|
291
|
+
slots: {
|
|
292
|
+
activator: `
|
|
293
|
+
<template #activator="{ openDialog }">
|
|
294
|
+
<button @click="openDialog" @keydown.enter="openDialog">
|
|
295
|
+
Open
|
|
296
|
+
</button>
|
|
297
|
+
</template>
|
|
298
|
+
`,
|
|
299
|
+
content: `
|
|
300
|
+
<template #content="{ closeDialog }">
|
|
301
|
+
<button @click="closeDialog" @keydown.escape="closeDialog">
|
|
302
|
+
Close
|
|
303
|
+
</button>
|
|
304
|
+
</template>
|
|
305
|
+
`
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
expect(wrapper.find('button').exists()).toBe(true);
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// Test console logging
|
|
314
|
+
describe('Console Logging', () => {
|
|
315
|
+
it('logs when opening dialog', () => {
|
|
316
|
+
const wrapper = mount(Dialog);
|
|
317
|
+
|
|
318
|
+
wrapper.vm.openDialog();
|
|
319
|
+
|
|
320
|
+
expect(console.log).toHaveBeenCalledWith('entereed 1');
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it('logs when closing dialog', () => {
|
|
324
|
+
const wrapper = mount(Dialog);
|
|
325
|
+
|
|
326
|
+
wrapper.vm.closeDialog();
|
|
327
|
+
|
|
328
|
+
expect(console.log).toHaveBeenCalledWith('entereed 2');
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('logs multiple times for multiple operations', () => {
|
|
332
|
+
const wrapper = mount(Dialog);
|
|
333
|
+
|
|
334
|
+
wrapper.vm.openDialog();
|
|
335
|
+
wrapper.vm.closeDialog();
|
|
336
|
+
wrapper.vm.openDialog();
|
|
337
|
+
|
|
338
|
+
expect(console.log).toHaveBeenCalledTimes(3);
|
|
339
|
+
expect(console.log).toHaveBeenNthCalledWith(1, 'entereed 1');
|
|
340
|
+
expect(console.log).toHaveBeenNthCalledWith(2, 'entereed 2');
|
|
341
|
+
expect(console.log).toHaveBeenNthCalledWith(3, 'entereed 1');
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
// Test edge cases
|
|
346
|
+
describe('Edge Cases', () => {
|
|
347
|
+
it('handles empty activator slot', () => {
|
|
348
|
+
const wrapper = mount(Dialog, {
|
|
349
|
+
slots: {
|
|
350
|
+
activator: ''
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
355
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('handles empty content slot', () => {
|
|
359
|
+
const wrapper = mount(Dialog, {
|
|
360
|
+
slots: {
|
|
361
|
+
content: ''
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
expect(wrapper.find('[data-testid="v-dialog"]').exists()).toBe(true);
|
|
366
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('handles no slots provided', () => {
|
|
370
|
+
const wrapper = mount(Dialog);
|
|
371
|
+
|
|
372
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
373
|
+
expect(wrapper.find('[data-testid="v-dialog"]').exists()).toBe(true);
|
|
374
|
+
expect(wrapper.vm.dialog).toBe(false);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it('handles rapid open/close calls', () => {
|
|
378
|
+
const wrapper = mount(Dialog);
|
|
379
|
+
|
|
380
|
+
// Rapid calls
|
|
381
|
+
wrapper.vm.openDialog();
|
|
382
|
+
wrapper.vm.closeDialog();
|
|
383
|
+
wrapper.vm.openDialog();
|
|
384
|
+
wrapper.vm.closeDialog();
|
|
385
|
+
wrapper.vm.openDialog();
|
|
386
|
+
|
|
387
|
+
expect(wrapper.vm.dialog).toBe(true);
|
|
388
|
+
expect(console.log).toHaveBeenCalledTimes(5);
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
// Test complex slot scenarios
|
|
393
|
+
describe('Complex Slot Scenarios', () => {
|
|
394
|
+
it('supports complex activator with multiple elements', () => {
|
|
395
|
+
const wrapper = mount(Dialog, {
|
|
396
|
+
slots: {
|
|
397
|
+
activator: `
|
|
398
|
+
<template #activator="{ openDialog }">
|
|
399
|
+
<div class="activator-container">
|
|
400
|
+
<button @click="openDialog" data-testid="primary-button">
|
|
401
|
+
Primary Open
|
|
402
|
+
</button>
|
|
403
|
+
<button @click="openDialog" data-testid="secondary-button">
|
|
404
|
+
Secondary Open
|
|
405
|
+
</button>
|
|
406
|
+
</div>
|
|
407
|
+
</template>
|
|
408
|
+
`
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
expect(wrapper.find('.activator-container').exists()).toBe(true);
|
|
413
|
+
expect(wrapper.find('[data-testid="primary-button"]').exists()).toBe(true);
|
|
414
|
+
expect(wrapper.find('[data-testid="secondary-button"]').exists()).toBe(true);
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
it('supports complex content with multiple interaction elements', () => {
|
|
418
|
+
const wrapper = mount(Dialog, {
|
|
419
|
+
slots: {
|
|
420
|
+
content: `
|
|
421
|
+
<template #content="{ closeDialog }">
|
|
422
|
+
<div class="dialog-content">
|
|
423
|
+
<header>
|
|
424
|
+
<h1>Dialog Title</h1>
|
|
425
|
+
<button @click="closeDialog" data-testid="header-close">×</button>
|
|
426
|
+
</header>
|
|
427
|
+
<main>
|
|
428
|
+
<p>Dialog content goes here</p>
|
|
429
|
+
</main>
|
|
430
|
+
<footer>
|
|
431
|
+
<button @click="closeDialog" data-testid="cancel-button">
|
|
432
|
+
Cancel
|
|
433
|
+
</button>
|
|
434
|
+
<button @click="closeDialog" data-testid="confirm-button">
|
|
435
|
+
Confirm
|
|
436
|
+
</button>
|
|
437
|
+
</footer>
|
|
438
|
+
</div>
|
|
439
|
+
</template>
|
|
440
|
+
`
|
|
441
|
+
}
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
expect(wrapper.find('.dialog-content').exists()).toBe(true);
|
|
445
|
+
expect(wrapper.find('[data-testid="header-close"]').exists()).toBe(true);
|
|
446
|
+
expect(wrapper.find('[data-testid="cancel-button"]').exists()).toBe(true);
|
|
447
|
+
expect(wrapper.find('[data-testid="confirm-button"]').exists()).toBe(true);
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
it('handles nested components in slots', () => {
|
|
451
|
+
const wrapper = mount(Dialog, {
|
|
452
|
+
slots: {
|
|
453
|
+
activator: `
|
|
454
|
+
<template #activator="{ openDialog }">
|
|
455
|
+
<div class="nested-component">
|
|
456
|
+
<span>Click to open:</span>
|
|
457
|
+
<button @click="openDialog">Open Dialog</button>
|
|
458
|
+
</div>
|
|
459
|
+
</template>
|
|
460
|
+
`,
|
|
461
|
+
content: `
|
|
462
|
+
<template #content="{ closeDialog }">
|
|
463
|
+
<div class="modal-wrapper">
|
|
464
|
+
<div class="modal-header">
|
|
465
|
+
<h2>Nested Modal</h2>
|
|
466
|
+
</div>
|
|
467
|
+
<div class="modal-body">
|
|
468
|
+
<p>This is a nested component structure</p>
|
|
469
|
+
</div>
|
|
470
|
+
<div class="modal-footer">
|
|
471
|
+
<button @click="closeDialog">Close</button>
|
|
472
|
+
</div>
|
|
473
|
+
</div>
|
|
474
|
+
</template>
|
|
475
|
+
`
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
expect(wrapper.find('.nested-component').exists()).toBe(true);
|
|
480
|
+
expect(wrapper.find('.modal-wrapper').exists()).toBe(true);
|
|
481
|
+
expect(wrapper.find('.modal-header').exists()).toBe(true);
|
|
482
|
+
expect(wrapper.find('.modal-body').exists()).toBe(true);
|
|
483
|
+
expect(wrapper.find('.modal-footer').exists()).toBe(true);
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
486
|
});
|