@zap-wunschlachen/wl-shared-components 1.0.38 → 1.0.40
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 +33 -33
- 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 +234 -232
- package/src/assets/css/variables.css +112 -109
- 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 +118 -118
- package/src/components/Button/Button.vue +174 -174
- package/src/components/CheckBox/CheckBox.css +214 -214
- package/src/components/CheckBox/Checkbox.vue +138 -138
- 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 +38 -38
- package/src/components/EditField/EditField.css +19 -19
- package/src/components/EditField/EditField.vue +202 -202
- package/src/components/ErrorPage/ErrorPage.css +172 -172
- 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/{calendar.vue → Calendar.vue} +17 -17
- 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/RingNotification.vue +54 -54
- package/src/components/Icons/SolidArrowRight.vue +14 -14
- 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 +253 -253
- 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 +71 -71
- package/src/components/MaintenanceBanner/MaintenanceBanner.css +353 -353
- package/src/components/MaintenanceBanner/MaintenanceBanner.vue +127 -127
- package/src/components/MaintenanceBanner/MaintenanceIllustration.vue +54 -54
- 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 +151 -151
- 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 +316 -316
- 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/accessibility.css +218 -218
- package/src/components/index.ts +29 -29
- 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 +141 -141
- 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 +116 -109
- 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/accessibility/component-a11y.spec.ts +469 -469
- package/tests/unit/components/Accordion/AccordionGroup.spec.ts +228 -228
- package/tests/unit/components/Accordion/AccordionGroup.spec.ts.skip +342 -342
- package/tests/unit/components/Accordion/AccordionItem.spec.ts +292 -292
- package/tests/unit/components/Accordion/AccordionItem.spec.ts.skip +383 -383
- package/tests/unit/components/Appointment/AnamneseNotification.spec.ts +176 -176
- 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/Background/Background.spec.ts +177 -177
- 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/ErrorPage/ErrorPage.spec.ts +313 -313
- package/tests/unit/components/ErrorPage/ErrorPageLogo.spec.ts +153 -153
- 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/AdvanceAppointments.spec.ts +61 -61
- 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/Logo.spec.ts +228 -228
- package/tests/unit/components/Icons/MiniLogo.spec.ts +38 -38
- package/tests/unit/components/Icons/RingNotification.spec.ts +393 -393
- package/tests/unit/components/Icons/SolidArrowRight.spec.ts +49 -49
- 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/components/Loader/Loader.spec.ts +197 -197
- package/tests/unit/components/MaintenanceBanner/MaintenanceBanner.spec.ts +302 -302
- 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/tests/unit/utils/accessibility.spec.ts +318 -318
- package/tsconfig.json +26 -26
- package/vite.config.ts +29 -29
- package/vitest.config.ts +83 -83
|
@@ -1,545 +1,545 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import { mount } from '@vue/test-utils';
|
|
3
|
-
import Checkbox from '@components/CheckBox/Checkbox.vue';
|
|
4
|
-
|
|
5
|
-
describe('Checkbox', () => {
|
|
6
|
-
// Test default behavior and rendering
|
|
7
|
-
describe('Default Behavior', () => {
|
|
8
|
-
it('renders with default props', () => {
|
|
9
|
-
const wrapper = mount(Checkbox);
|
|
10
|
-
|
|
11
|
-
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
12
|
-
expect(wrapper.find('input[type="checkbox"]').exists()).toBe(true);
|
|
13
|
-
expect(wrapper.vm.success).toBe(false);
|
|
14
|
-
expect(wrapper.vm.error).toBe(false);
|
|
15
|
-
expect(wrapper.vm.disabled).toBe(false);
|
|
16
|
-
expect(wrapper.vm.value).toBe('checkbox');
|
|
17
|
-
expect(wrapper.vm.density).toBe('default');
|
|
18
|
-
expect(Array.isArray(wrapper.vm.modelValue)).toBe(true);
|
|
19
|
-
expect(wrapper.vm.modelValue).toEqual([]);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('renders with label', () => {
|
|
23
|
-
const wrapper = mount(Checkbox, {
|
|
24
|
-
props: {
|
|
25
|
-
label: 'Test Checkbox'
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
expect(wrapper.text()).toBe('Test Checkbox');
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('applies default CSS classes', () => {
|
|
33
|
-
const wrapper = mount(Checkbox);
|
|
34
|
-
|
|
35
|
-
expect(wrapper.find('.label').exists()).toBe(true);
|
|
36
|
-
expect(wrapper.find('.checkbox-container').exists()).toBe(true);
|
|
37
|
-
expect(wrapper.find('.input-checkbox').exists()).toBe(true);
|
|
38
|
-
expect(wrapper.find('.density-default').exists()).toBe(true);
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
// Test v-model with arrays (multiple selection)
|
|
43
|
-
describe('v-model with Arrays', () => {
|
|
44
|
-
it('handles unchecked state with empty array', () => {
|
|
45
|
-
const wrapper = mount(Checkbox, {
|
|
46
|
-
props: {
|
|
47
|
-
modelValue: [],
|
|
48
|
-
value: 'option1'
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
expect(wrapper.vm.isChecked).toBe(false);
|
|
53
|
-
expect(wrapper.find('input').element.checked).toBe(false);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('handles checked state when value is in array', () => {
|
|
57
|
-
const wrapper = mount(Checkbox, {
|
|
58
|
-
props: {
|
|
59
|
-
modelValue: ['option1', 'option2'],
|
|
60
|
-
value: 'option1'
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
expect(wrapper.vm.isChecked).toBe(true);
|
|
65
|
-
expect(wrapper.find('input').element.checked).toBe(true);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('handles unchecked state when value is not in array', () => {
|
|
69
|
-
const wrapper = mount(Checkbox, {
|
|
70
|
-
props: {
|
|
71
|
-
modelValue: ['option2', 'option3'],
|
|
72
|
-
value: 'option1'
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
expect(wrapper.vm.isChecked).toBe(false);
|
|
77
|
-
expect(wrapper.find('input').element.checked).toBe(false);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('adds value to array when checked', async () => {
|
|
81
|
-
const wrapper = mount(Checkbox, {
|
|
82
|
-
props: {
|
|
83
|
-
modelValue: [],
|
|
84
|
-
value: 'option1'
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
const input = wrapper.find('input');
|
|
89
|
-
await input.setValue(true);
|
|
90
|
-
|
|
91
|
-
expect(wrapper.emitted('update:modelValue')).toBeTruthy();
|
|
92
|
-
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([['option1']]);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('removes value from array when unchecked', async () => {
|
|
96
|
-
const wrapper = mount(Checkbox, {
|
|
97
|
-
props: {
|
|
98
|
-
modelValue: ['option1', 'option2'],
|
|
99
|
-
value: 'option1'
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
const input = wrapper.find('input');
|
|
104
|
-
await input.setValue(false);
|
|
105
|
-
|
|
106
|
-
expect(wrapper.emitted('update:modelValue')).toBeTruthy();
|
|
107
|
-
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([['option2']]);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('maintains other values when adding new value', async () => {
|
|
111
|
-
const wrapper = mount(Checkbox, {
|
|
112
|
-
props: {
|
|
113
|
-
modelValue: ['option2', 'option3'],
|
|
114
|
-
value: 'option1'
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
const input = wrapper.find('input');
|
|
119
|
-
await input.setValue(true);
|
|
120
|
-
|
|
121
|
-
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([['option2', 'option3', 'option1']]);
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
// Test v-model with boolean (single selection)
|
|
126
|
-
describe('v-model with Boolean', () => {
|
|
127
|
-
it('handles false boolean value', () => {
|
|
128
|
-
const wrapper = mount(Checkbox, {
|
|
129
|
-
props: {
|
|
130
|
-
modelValue: false,
|
|
131
|
-
value: 'option1'
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
expect(wrapper.vm.isChecked).toBe(false);
|
|
136
|
-
expect(wrapper.find('input').element.checked).toBe(false);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it('handles true boolean value', () => {
|
|
140
|
-
const wrapper = mount(Checkbox, {
|
|
141
|
-
props: {
|
|
142
|
-
modelValue: true,
|
|
143
|
-
value: 'option1'
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
expect(wrapper.vm.isChecked).toBe(true);
|
|
148
|
-
expect(wrapper.find('input').element.checked).toBe(true);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('emits true when checked with boolean model', async () => {
|
|
152
|
-
const wrapper = mount(Checkbox, {
|
|
153
|
-
props: {
|
|
154
|
-
modelValue: false,
|
|
155
|
-
value: 'option1'
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
const input = wrapper.find('input');
|
|
160
|
-
await input.setValue(true);
|
|
161
|
-
|
|
162
|
-
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([true]);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('emits false when unchecked with boolean model', async () => {
|
|
166
|
-
const wrapper = mount(Checkbox, {
|
|
167
|
-
props: {
|
|
168
|
-
modelValue: true,
|
|
169
|
-
value: 'option1'
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
const input = wrapper.find('input');
|
|
174
|
-
await input.setValue(false);
|
|
175
|
-
|
|
176
|
-
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([false]);
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
// Test state props
|
|
181
|
-
describe('State Props', () => {
|
|
182
|
-
it('applies success state', () => {
|
|
183
|
-
const wrapper = mount(Checkbox, {
|
|
184
|
-
props: {
|
|
185
|
-
success: true
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
expect(wrapper.find('.label-success').exists()).toBe(true);
|
|
190
|
-
expect(wrapper.find('.input-success').exists()).toBe(true);
|
|
191
|
-
expect(wrapper.vm.success).toBe(true);
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('applies error state', () => {
|
|
195
|
-
const wrapper = mount(Checkbox, {
|
|
196
|
-
props: {
|
|
197
|
-
error: true
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
expect(wrapper.find('.label-error').exists()).toBe(true);
|
|
202
|
-
expect(wrapper.find('.input-error').exists()).toBe(true);
|
|
203
|
-
expect(wrapper.vm.error).toBe(true);
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
it('applies disabled state', () => {
|
|
207
|
-
const wrapper = mount(Checkbox, {
|
|
208
|
-
props: {
|
|
209
|
-
disabled: true
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
expect(wrapper.find('.label-disabled').exists()).toBe(true);
|
|
214
|
-
expect(wrapper.find('.input-disabled').exists()).toBe(true);
|
|
215
|
-
expect(wrapper.find('input').element.disabled).toBe(true);
|
|
216
|
-
expect(wrapper.vm.disabled).toBe(true);
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
it('handles multiple states together', () => {
|
|
220
|
-
const wrapper = mount(Checkbox, {
|
|
221
|
-
props: {
|
|
222
|
-
success: true,
|
|
223
|
-
error: true,
|
|
224
|
-
disabled: true
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
expect(wrapper.find('.label-success').exists()).toBe(true);
|
|
229
|
-
expect(wrapper.find('.label-error').exists()).toBe(true);
|
|
230
|
-
expect(wrapper.find('.label-disabled').exists()).toBe(true);
|
|
231
|
-
expect(wrapper.find('.input-success').exists()).toBe(true);
|
|
232
|
-
expect(wrapper.find('.input-error').exists()).toBe(true);
|
|
233
|
-
expect(wrapper.find('.input-disabled').exists()).toBe(true);
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
// Test density prop and validation
|
|
238
|
-
describe('Density', () => {
|
|
239
|
-
it('applies default density', () => {
|
|
240
|
-
const wrapper = mount(Checkbox);
|
|
241
|
-
expect(wrapper.find('.density-default').exists()).toBe(true);
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
it('applies comfortable density', () => {
|
|
245
|
-
const wrapper = mount(Checkbox, {
|
|
246
|
-
props: {
|
|
247
|
-
density: 'comfortable'
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
expect(wrapper.find('.density-comfortable').exists()).toBe(true);
|
|
252
|
-
expect(wrapper.vm.density).toBe('comfortable');
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
it('applies compact density', () => {
|
|
256
|
-
const wrapper = mount(Checkbox, {
|
|
257
|
-
props: {
|
|
258
|
-
density: 'compact'
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
expect(wrapper.find('.density-compact').exists()).toBe(true);
|
|
263
|
-
expect(wrapper.vm.density).toBe('compact');
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
it('validates density prop with valid values', () => {
|
|
267
|
-
const validValues = ['comfortable', 'default', 'compact'];
|
|
268
|
-
|
|
269
|
-
validValues.forEach(density => {
|
|
270
|
-
expect(() => {
|
|
271
|
-
mount(Checkbox, {
|
|
272
|
-
props: { density }
|
|
273
|
-
});
|
|
274
|
-
}).not.toThrow();
|
|
275
|
-
});
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
// Test custom value prop
|
|
280
|
-
describe('Value Prop', () => {
|
|
281
|
-
it('uses custom value', () => {
|
|
282
|
-
const wrapper = mount(Checkbox, {
|
|
283
|
-
props: {
|
|
284
|
-
value: 'custom-value'
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
expect(wrapper.find('input').element.name).toBe('custom-value');
|
|
289
|
-
expect(wrapper.vm.value).toBe('custom-value');
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
it('uses default value when not provided', () => {
|
|
293
|
-
const wrapper = mount(Checkbox);
|
|
294
|
-
|
|
295
|
-
expect(wrapper.find('input').element.name).toBe('checkbox');
|
|
296
|
-
expect(wrapper.vm.value).toBe('checkbox');
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
// Test events
|
|
301
|
-
describe('Events', () => {
|
|
302
|
-
it('emits update:modelValue on change', async () => {
|
|
303
|
-
const wrapper = mount(Checkbox, {
|
|
304
|
-
props: {
|
|
305
|
-
modelValue: false,
|
|
306
|
-
value: 'test'
|
|
307
|
-
}
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
const input = wrapper.find('input');
|
|
311
|
-
await input.setValue(true);
|
|
312
|
-
|
|
313
|
-
expect(wrapper.emitted('update:modelValue')).toBeTruthy();
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
it('emits input-error event with correct payload', async () => {
|
|
317
|
-
const wrapper = mount(Checkbox, {
|
|
318
|
-
props: {
|
|
319
|
-
modelValue: false,
|
|
320
|
-
value: 'test-checkbox'
|
|
321
|
-
}
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
const input = wrapper.find('input');
|
|
325
|
-
await input.setValue(true);
|
|
326
|
-
|
|
327
|
-
expect(wrapper.emitted('input-error')).toBeTruthy();
|
|
328
|
-
expect(wrapper.emitted('input-error')?.[0]).toEqual([{ id: 'test-checkbox', isError: false }]);
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
it('emits input-error with isError: true when unchecked', async () => {
|
|
332
|
-
const wrapper = mount(Checkbox, {
|
|
333
|
-
props: {
|
|
334
|
-
modelValue: true,
|
|
335
|
-
value: 'test-checkbox'
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
const input = wrapper.find('input');
|
|
340
|
-
await input.setValue(false);
|
|
341
|
-
|
|
342
|
-
expect(wrapper.emitted('input-error')?.[0]).toEqual([{ id: 'test-checkbox', isError: true }]);
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
it('does not emit events when disabled', async () => {
|
|
346
|
-
const wrapper = mount(Checkbox, {
|
|
347
|
-
props: {
|
|
348
|
-
disabled: true,
|
|
349
|
-
modelValue: false
|
|
350
|
-
}
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
const input = wrapper.find('input');
|
|
354
|
-
|
|
355
|
-
// Try to trigger change event on disabled input
|
|
356
|
-
await input.trigger('change');
|
|
357
|
-
|
|
358
|
-
// Events should not be emitted for disabled checkbox
|
|
359
|
-
expect(wrapper.emitted('update:modelValue')).toBeFalsy();
|
|
360
|
-
expect(wrapper.emitted('input-error')).toBeFalsy();
|
|
361
|
-
});
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
// Test computed properties
|
|
365
|
-
describe('Computed Properties', () => {
|
|
366
|
-
it('computes labelClasses correctly', () => {
|
|
367
|
-
const wrapper = mount(Checkbox, {
|
|
368
|
-
props: {
|
|
369
|
-
success: true,
|
|
370
|
-
error: false,
|
|
371
|
-
disabled: false
|
|
372
|
-
}
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
const labelClasses = wrapper.vm.labelClasses;
|
|
376
|
-
expect(labelClasses.label).toBe(true);
|
|
377
|
-
expect(labelClasses['label-success']).toBe(true);
|
|
378
|
-
expect(labelClasses['label-error']).toBe(false);
|
|
379
|
-
expect(labelClasses['label-disabled']).toBe(false);
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
it('computes inputClasses correctly', () => {
|
|
383
|
-
const wrapper = mount(Checkbox, {
|
|
384
|
-
props: {
|
|
385
|
-
success: false,
|
|
386
|
-
error: true,
|
|
387
|
-
disabled: false,
|
|
388
|
-
density: 'compact'
|
|
389
|
-
}
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
const inputClasses = wrapper.vm.inputClasses;
|
|
393
|
-
expect(inputClasses['input-checkbox']).toBe(true);
|
|
394
|
-
expect(inputClasses['input-success']).toBe(false);
|
|
395
|
-
expect(inputClasses['input-error']).toBe(true);
|
|
396
|
-
expect(inputClasses['input-disabled']).toBe(false);
|
|
397
|
-
expect(inputClasses['density-compact']).toBe(true);
|
|
398
|
-
});
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
// Test accessibility
|
|
402
|
-
describe('Accessibility', () => {
|
|
403
|
-
it('has proper label association', () => {
|
|
404
|
-
const wrapper = mount(Checkbox, {
|
|
405
|
-
props: {
|
|
406
|
-
label: 'Accessible checkbox',
|
|
407
|
-
value: 'accessible'
|
|
408
|
-
}
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
const label = wrapper.find('label');
|
|
412
|
-
const input = wrapper.find('input');
|
|
413
|
-
|
|
414
|
-
expect(label.exists()).toBe(true);
|
|
415
|
-
expect(input.element.name).toBe('accessible');
|
|
416
|
-
expect(wrapper.text()).toContain('Accessible checkbox');
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
it('maintains accessibility when disabled', () => {
|
|
420
|
-
const wrapper = mount(Checkbox, {
|
|
421
|
-
props: {
|
|
422
|
-
label: 'Disabled checkbox',
|
|
423
|
-
disabled: true
|
|
424
|
-
}
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
expect(wrapper.find('input').element.disabled).toBe(true);
|
|
428
|
-
expect(wrapper.text()).toContain('Disabled checkbox');
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
it('has data-testid for testing', () => {
|
|
432
|
-
const wrapper = mount(Checkbox);
|
|
433
|
-
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
434
|
-
});
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
// Test edge cases
|
|
438
|
-
describe('Edge Cases', () => {
|
|
439
|
-
it('handles empty label', () => {
|
|
440
|
-
const wrapper = mount(Checkbox, {
|
|
441
|
-
props: {
|
|
442
|
-
label: ''
|
|
443
|
-
}
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
expect(wrapper.text().trim()).toBe('');
|
|
447
|
-
});
|
|
448
|
-
|
|
449
|
-
it('handles undefined label', () => {
|
|
450
|
-
const wrapper = mount(Checkbox, {
|
|
451
|
-
props: {
|
|
452
|
-
label: undefined
|
|
453
|
-
}
|
|
454
|
-
});
|
|
455
|
-
|
|
456
|
-
expect(wrapper.vm.label).toBeUndefined();
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
it('handles large arrays in modelValue', () => {
|
|
460
|
-
const largeArray = Array.from({ length: 1000 }, (_, i) => `option${i}`);
|
|
461
|
-
const wrapper = mount(Checkbox, {
|
|
462
|
-
props: {
|
|
463
|
-
modelValue: largeArray,
|
|
464
|
-
value: 'option500'
|
|
465
|
-
}
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
expect(wrapper.vm.isChecked).toBe(true);
|
|
469
|
-
});
|
|
470
|
-
|
|
471
|
-
it('handles special characters in value', () => {
|
|
472
|
-
const wrapper = mount(Checkbox, {
|
|
473
|
-
props: {
|
|
474
|
-
value: 'special!@#$%^&*()_+{}|:"<>?`~value',
|
|
475
|
-
modelValue: []
|
|
476
|
-
}
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
expect(wrapper.vm.value).toBe('special!@#$%^&*()_+{}|:"<>?`~value');
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
it('handles rapid state changes', async () => {
|
|
483
|
-
const wrapper = mount(Checkbox, {
|
|
484
|
-
props: {
|
|
485
|
-
modelValue: [],
|
|
486
|
-
value: 'rapid-test'
|
|
487
|
-
}
|
|
488
|
-
});
|
|
489
|
-
|
|
490
|
-
const input = wrapper.find('input');
|
|
491
|
-
|
|
492
|
-
// Rapid changes
|
|
493
|
-
await input.setValue(true);
|
|
494
|
-
await input.setValue(false);
|
|
495
|
-
await input.setValue(true);
|
|
496
|
-
|
|
497
|
-
expect(wrapper.emitted('update:modelValue')).toHaveLength(3);
|
|
498
|
-
expect(wrapper.emitted('input-error')).toHaveLength(3);
|
|
499
|
-
});
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
// Test complex scenarios
|
|
503
|
-
describe('Complex Scenarios', () => {
|
|
504
|
-
it('works with all props combined', () => {
|
|
505
|
-
const wrapper = mount(Checkbox, {
|
|
506
|
-
props: {
|
|
507
|
-
label: 'Complex checkbox',
|
|
508
|
-
success: false,
|
|
509
|
-
error: true,
|
|
510
|
-
disabled: false,
|
|
511
|
-
value: 'complex-value',
|
|
512
|
-
modelValue: ['other-value', 'complex-value'],
|
|
513
|
-
density: 'comfortable'
|
|
514
|
-
}
|
|
515
|
-
});
|
|
516
|
-
|
|
517
|
-
expect(wrapper.vm.isChecked).toBe(true);
|
|
518
|
-
expect(wrapper.find('.label-error').exists()).toBe(true);
|
|
519
|
-
expect(wrapper.find('.density-comfortable').exists()).toBe(true);
|
|
520
|
-
expect(wrapper.text()).toBe('Complex checkbox');
|
|
521
|
-
});
|
|
522
|
-
|
|
523
|
-
it('handles switching between array and boolean modelValue types', async () => {
|
|
524
|
-
const wrapper = mount(Checkbox, {
|
|
525
|
-
props: {
|
|
526
|
-
modelValue: [],
|
|
527
|
-
value: 'test'
|
|
528
|
-
}
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
expect(wrapper.vm.isChecked).toBe(false);
|
|
532
|
-
|
|
533
|
-
// Switch to boolean
|
|
534
|
-
await wrapper.setProps({ modelValue: true });
|
|
535
|
-
expect(wrapper.vm.isChecked).toBe(true);
|
|
536
|
-
|
|
537
|
-
// Switch back to array
|
|
538
|
-
await wrapper.setProps({ modelValue: ['test'] });
|
|
539
|
-
expect(wrapper.vm.isChecked).toBe(true);
|
|
540
|
-
|
|
541
|
-
await wrapper.setProps({ modelValue: [] });
|
|
542
|
-
expect(wrapper.vm.isChecked).toBe(false);
|
|
543
|
-
});
|
|
544
|
-
});
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import Checkbox from '@components/CheckBox/Checkbox.vue';
|
|
4
|
+
|
|
5
|
+
describe('Checkbox', () => {
|
|
6
|
+
// Test default behavior and rendering
|
|
7
|
+
describe('Default Behavior', () => {
|
|
8
|
+
it('renders with default props', () => {
|
|
9
|
+
const wrapper = mount(Checkbox);
|
|
10
|
+
|
|
11
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
12
|
+
expect(wrapper.find('input[type="checkbox"]').exists()).toBe(true);
|
|
13
|
+
expect(wrapper.vm.success).toBe(false);
|
|
14
|
+
expect(wrapper.vm.error).toBe(false);
|
|
15
|
+
expect(wrapper.vm.disabled).toBe(false);
|
|
16
|
+
expect(wrapper.vm.value).toBe('checkbox');
|
|
17
|
+
expect(wrapper.vm.density).toBe('default');
|
|
18
|
+
expect(Array.isArray(wrapper.vm.modelValue)).toBe(true);
|
|
19
|
+
expect(wrapper.vm.modelValue).toEqual([]);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('renders with label', () => {
|
|
23
|
+
const wrapper = mount(Checkbox, {
|
|
24
|
+
props: {
|
|
25
|
+
label: 'Test Checkbox'
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
expect(wrapper.text()).toBe('Test Checkbox');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('applies default CSS classes', () => {
|
|
33
|
+
const wrapper = mount(Checkbox);
|
|
34
|
+
|
|
35
|
+
expect(wrapper.find('.label').exists()).toBe(true);
|
|
36
|
+
expect(wrapper.find('.checkbox-container').exists()).toBe(true);
|
|
37
|
+
expect(wrapper.find('.input-checkbox').exists()).toBe(true);
|
|
38
|
+
expect(wrapper.find('.density-default').exists()).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Test v-model with arrays (multiple selection)
|
|
43
|
+
describe('v-model with Arrays', () => {
|
|
44
|
+
it('handles unchecked state with empty array', () => {
|
|
45
|
+
const wrapper = mount(Checkbox, {
|
|
46
|
+
props: {
|
|
47
|
+
modelValue: [],
|
|
48
|
+
value: 'option1'
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
expect(wrapper.vm.isChecked).toBe(false);
|
|
53
|
+
expect(wrapper.find('input').element.checked).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('handles checked state when value is in array', () => {
|
|
57
|
+
const wrapper = mount(Checkbox, {
|
|
58
|
+
props: {
|
|
59
|
+
modelValue: ['option1', 'option2'],
|
|
60
|
+
value: 'option1'
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
expect(wrapper.vm.isChecked).toBe(true);
|
|
65
|
+
expect(wrapper.find('input').element.checked).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('handles unchecked state when value is not in array', () => {
|
|
69
|
+
const wrapper = mount(Checkbox, {
|
|
70
|
+
props: {
|
|
71
|
+
modelValue: ['option2', 'option3'],
|
|
72
|
+
value: 'option1'
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
expect(wrapper.vm.isChecked).toBe(false);
|
|
77
|
+
expect(wrapper.find('input').element.checked).toBe(false);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('adds value to array when checked', async () => {
|
|
81
|
+
const wrapper = mount(Checkbox, {
|
|
82
|
+
props: {
|
|
83
|
+
modelValue: [],
|
|
84
|
+
value: 'option1'
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const input = wrapper.find('input');
|
|
89
|
+
await input.setValue(true);
|
|
90
|
+
|
|
91
|
+
expect(wrapper.emitted('update:modelValue')).toBeTruthy();
|
|
92
|
+
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([['option1']]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('removes value from array when unchecked', async () => {
|
|
96
|
+
const wrapper = mount(Checkbox, {
|
|
97
|
+
props: {
|
|
98
|
+
modelValue: ['option1', 'option2'],
|
|
99
|
+
value: 'option1'
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const input = wrapper.find('input');
|
|
104
|
+
await input.setValue(false);
|
|
105
|
+
|
|
106
|
+
expect(wrapper.emitted('update:modelValue')).toBeTruthy();
|
|
107
|
+
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([['option2']]);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('maintains other values when adding new value', async () => {
|
|
111
|
+
const wrapper = mount(Checkbox, {
|
|
112
|
+
props: {
|
|
113
|
+
modelValue: ['option2', 'option3'],
|
|
114
|
+
value: 'option1'
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const input = wrapper.find('input');
|
|
119
|
+
await input.setValue(true);
|
|
120
|
+
|
|
121
|
+
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([['option2', 'option3', 'option1']]);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Test v-model with boolean (single selection)
|
|
126
|
+
describe('v-model with Boolean', () => {
|
|
127
|
+
it('handles false boolean value', () => {
|
|
128
|
+
const wrapper = mount(Checkbox, {
|
|
129
|
+
props: {
|
|
130
|
+
modelValue: false,
|
|
131
|
+
value: 'option1'
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
expect(wrapper.vm.isChecked).toBe(false);
|
|
136
|
+
expect(wrapper.find('input').element.checked).toBe(false);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('handles true boolean value', () => {
|
|
140
|
+
const wrapper = mount(Checkbox, {
|
|
141
|
+
props: {
|
|
142
|
+
modelValue: true,
|
|
143
|
+
value: 'option1'
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
expect(wrapper.vm.isChecked).toBe(true);
|
|
148
|
+
expect(wrapper.find('input').element.checked).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('emits true when checked with boolean model', async () => {
|
|
152
|
+
const wrapper = mount(Checkbox, {
|
|
153
|
+
props: {
|
|
154
|
+
modelValue: false,
|
|
155
|
+
value: 'option1'
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const input = wrapper.find('input');
|
|
160
|
+
await input.setValue(true);
|
|
161
|
+
|
|
162
|
+
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([true]);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('emits false when unchecked with boolean model', async () => {
|
|
166
|
+
const wrapper = mount(Checkbox, {
|
|
167
|
+
props: {
|
|
168
|
+
modelValue: true,
|
|
169
|
+
value: 'option1'
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
const input = wrapper.find('input');
|
|
174
|
+
await input.setValue(false);
|
|
175
|
+
|
|
176
|
+
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([false]);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Test state props
|
|
181
|
+
describe('State Props', () => {
|
|
182
|
+
it('applies success state', () => {
|
|
183
|
+
const wrapper = mount(Checkbox, {
|
|
184
|
+
props: {
|
|
185
|
+
success: true
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
expect(wrapper.find('.label-success').exists()).toBe(true);
|
|
190
|
+
expect(wrapper.find('.input-success').exists()).toBe(true);
|
|
191
|
+
expect(wrapper.vm.success).toBe(true);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('applies error state', () => {
|
|
195
|
+
const wrapper = mount(Checkbox, {
|
|
196
|
+
props: {
|
|
197
|
+
error: true
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
expect(wrapper.find('.label-error').exists()).toBe(true);
|
|
202
|
+
expect(wrapper.find('.input-error').exists()).toBe(true);
|
|
203
|
+
expect(wrapper.vm.error).toBe(true);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('applies disabled state', () => {
|
|
207
|
+
const wrapper = mount(Checkbox, {
|
|
208
|
+
props: {
|
|
209
|
+
disabled: true
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
expect(wrapper.find('.label-disabled').exists()).toBe(true);
|
|
214
|
+
expect(wrapper.find('.input-disabled').exists()).toBe(true);
|
|
215
|
+
expect(wrapper.find('input').element.disabled).toBe(true);
|
|
216
|
+
expect(wrapper.vm.disabled).toBe(true);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('handles multiple states together', () => {
|
|
220
|
+
const wrapper = mount(Checkbox, {
|
|
221
|
+
props: {
|
|
222
|
+
success: true,
|
|
223
|
+
error: true,
|
|
224
|
+
disabled: true
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
expect(wrapper.find('.label-success').exists()).toBe(true);
|
|
229
|
+
expect(wrapper.find('.label-error').exists()).toBe(true);
|
|
230
|
+
expect(wrapper.find('.label-disabled').exists()).toBe(true);
|
|
231
|
+
expect(wrapper.find('.input-success').exists()).toBe(true);
|
|
232
|
+
expect(wrapper.find('.input-error').exists()).toBe(true);
|
|
233
|
+
expect(wrapper.find('.input-disabled').exists()).toBe(true);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// Test density prop and validation
|
|
238
|
+
describe('Density', () => {
|
|
239
|
+
it('applies default density', () => {
|
|
240
|
+
const wrapper = mount(Checkbox);
|
|
241
|
+
expect(wrapper.find('.density-default').exists()).toBe(true);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('applies comfortable density', () => {
|
|
245
|
+
const wrapper = mount(Checkbox, {
|
|
246
|
+
props: {
|
|
247
|
+
density: 'comfortable'
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
expect(wrapper.find('.density-comfortable').exists()).toBe(true);
|
|
252
|
+
expect(wrapper.vm.density).toBe('comfortable');
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('applies compact density', () => {
|
|
256
|
+
const wrapper = mount(Checkbox, {
|
|
257
|
+
props: {
|
|
258
|
+
density: 'compact'
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
expect(wrapper.find('.density-compact').exists()).toBe(true);
|
|
263
|
+
expect(wrapper.vm.density).toBe('compact');
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('validates density prop with valid values', () => {
|
|
267
|
+
const validValues = ['comfortable', 'default', 'compact'];
|
|
268
|
+
|
|
269
|
+
validValues.forEach(density => {
|
|
270
|
+
expect(() => {
|
|
271
|
+
mount(Checkbox, {
|
|
272
|
+
props: { density }
|
|
273
|
+
});
|
|
274
|
+
}).not.toThrow();
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// Test custom value prop
|
|
280
|
+
describe('Value Prop', () => {
|
|
281
|
+
it('uses custom value', () => {
|
|
282
|
+
const wrapper = mount(Checkbox, {
|
|
283
|
+
props: {
|
|
284
|
+
value: 'custom-value'
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
expect(wrapper.find('input').element.name).toBe('custom-value');
|
|
289
|
+
expect(wrapper.vm.value).toBe('custom-value');
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('uses default value when not provided', () => {
|
|
293
|
+
const wrapper = mount(Checkbox);
|
|
294
|
+
|
|
295
|
+
expect(wrapper.find('input').element.name).toBe('checkbox');
|
|
296
|
+
expect(wrapper.vm.value).toBe('checkbox');
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// Test events
|
|
301
|
+
describe('Events', () => {
|
|
302
|
+
it('emits update:modelValue on change', async () => {
|
|
303
|
+
const wrapper = mount(Checkbox, {
|
|
304
|
+
props: {
|
|
305
|
+
modelValue: false,
|
|
306
|
+
value: 'test'
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
const input = wrapper.find('input');
|
|
311
|
+
await input.setValue(true);
|
|
312
|
+
|
|
313
|
+
expect(wrapper.emitted('update:modelValue')).toBeTruthy();
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('emits input-error event with correct payload', async () => {
|
|
317
|
+
const wrapper = mount(Checkbox, {
|
|
318
|
+
props: {
|
|
319
|
+
modelValue: false,
|
|
320
|
+
value: 'test-checkbox'
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
const input = wrapper.find('input');
|
|
325
|
+
await input.setValue(true);
|
|
326
|
+
|
|
327
|
+
expect(wrapper.emitted('input-error')).toBeTruthy();
|
|
328
|
+
expect(wrapper.emitted('input-error')?.[0]).toEqual([{ id: 'test-checkbox', isError: false }]);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('emits input-error with isError: true when unchecked', async () => {
|
|
332
|
+
const wrapper = mount(Checkbox, {
|
|
333
|
+
props: {
|
|
334
|
+
modelValue: true,
|
|
335
|
+
value: 'test-checkbox'
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
const input = wrapper.find('input');
|
|
340
|
+
await input.setValue(false);
|
|
341
|
+
|
|
342
|
+
expect(wrapper.emitted('input-error')?.[0]).toEqual([{ id: 'test-checkbox', isError: true }]);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it('does not emit events when disabled', async () => {
|
|
346
|
+
const wrapper = mount(Checkbox, {
|
|
347
|
+
props: {
|
|
348
|
+
disabled: true,
|
|
349
|
+
modelValue: false
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
const input = wrapper.find('input');
|
|
354
|
+
|
|
355
|
+
// Try to trigger change event on disabled input
|
|
356
|
+
await input.trigger('change');
|
|
357
|
+
|
|
358
|
+
// Events should not be emitted for disabled checkbox
|
|
359
|
+
expect(wrapper.emitted('update:modelValue')).toBeFalsy();
|
|
360
|
+
expect(wrapper.emitted('input-error')).toBeFalsy();
|
|
361
|
+
});
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
// Test computed properties
|
|
365
|
+
describe('Computed Properties', () => {
|
|
366
|
+
it('computes labelClasses correctly', () => {
|
|
367
|
+
const wrapper = mount(Checkbox, {
|
|
368
|
+
props: {
|
|
369
|
+
success: true,
|
|
370
|
+
error: false,
|
|
371
|
+
disabled: false
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
const labelClasses = wrapper.vm.labelClasses;
|
|
376
|
+
expect(labelClasses.label).toBe(true);
|
|
377
|
+
expect(labelClasses['label-success']).toBe(true);
|
|
378
|
+
expect(labelClasses['label-error']).toBe(false);
|
|
379
|
+
expect(labelClasses['label-disabled']).toBe(false);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
it('computes inputClasses correctly', () => {
|
|
383
|
+
const wrapper = mount(Checkbox, {
|
|
384
|
+
props: {
|
|
385
|
+
success: false,
|
|
386
|
+
error: true,
|
|
387
|
+
disabled: false,
|
|
388
|
+
density: 'compact'
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
const inputClasses = wrapper.vm.inputClasses;
|
|
393
|
+
expect(inputClasses['input-checkbox']).toBe(true);
|
|
394
|
+
expect(inputClasses['input-success']).toBe(false);
|
|
395
|
+
expect(inputClasses['input-error']).toBe(true);
|
|
396
|
+
expect(inputClasses['input-disabled']).toBe(false);
|
|
397
|
+
expect(inputClasses['density-compact']).toBe(true);
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
// Test accessibility
|
|
402
|
+
describe('Accessibility', () => {
|
|
403
|
+
it('has proper label association', () => {
|
|
404
|
+
const wrapper = mount(Checkbox, {
|
|
405
|
+
props: {
|
|
406
|
+
label: 'Accessible checkbox',
|
|
407
|
+
value: 'accessible'
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
const label = wrapper.find('label');
|
|
412
|
+
const input = wrapper.find('input');
|
|
413
|
+
|
|
414
|
+
expect(label.exists()).toBe(true);
|
|
415
|
+
expect(input.element.name).toBe('accessible');
|
|
416
|
+
expect(wrapper.text()).toContain('Accessible checkbox');
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it('maintains accessibility when disabled', () => {
|
|
420
|
+
const wrapper = mount(Checkbox, {
|
|
421
|
+
props: {
|
|
422
|
+
label: 'Disabled checkbox',
|
|
423
|
+
disabled: true
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
expect(wrapper.find('input').element.disabled).toBe(true);
|
|
428
|
+
expect(wrapper.text()).toContain('Disabled checkbox');
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('has data-testid for testing', () => {
|
|
432
|
+
const wrapper = mount(Checkbox);
|
|
433
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
// Test edge cases
|
|
438
|
+
describe('Edge Cases', () => {
|
|
439
|
+
it('handles empty label', () => {
|
|
440
|
+
const wrapper = mount(Checkbox, {
|
|
441
|
+
props: {
|
|
442
|
+
label: ''
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
expect(wrapper.text().trim()).toBe('');
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
it('handles undefined label', () => {
|
|
450
|
+
const wrapper = mount(Checkbox, {
|
|
451
|
+
props: {
|
|
452
|
+
label: undefined
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
expect(wrapper.vm.label).toBeUndefined();
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
it('handles large arrays in modelValue', () => {
|
|
460
|
+
const largeArray = Array.from({ length: 1000 }, (_, i) => `option${i}`);
|
|
461
|
+
const wrapper = mount(Checkbox, {
|
|
462
|
+
props: {
|
|
463
|
+
modelValue: largeArray,
|
|
464
|
+
value: 'option500'
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
expect(wrapper.vm.isChecked).toBe(true);
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
it('handles special characters in value', () => {
|
|
472
|
+
const wrapper = mount(Checkbox, {
|
|
473
|
+
props: {
|
|
474
|
+
value: 'special!@#$%^&*()_+{}|:"<>?`~value',
|
|
475
|
+
modelValue: []
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
expect(wrapper.vm.value).toBe('special!@#$%^&*()_+{}|:"<>?`~value');
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
it('handles rapid state changes', async () => {
|
|
483
|
+
const wrapper = mount(Checkbox, {
|
|
484
|
+
props: {
|
|
485
|
+
modelValue: [],
|
|
486
|
+
value: 'rapid-test'
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
const input = wrapper.find('input');
|
|
491
|
+
|
|
492
|
+
// Rapid changes
|
|
493
|
+
await input.setValue(true);
|
|
494
|
+
await input.setValue(false);
|
|
495
|
+
await input.setValue(true);
|
|
496
|
+
|
|
497
|
+
expect(wrapper.emitted('update:modelValue')).toHaveLength(3);
|
|
498
|
+
expect(wrapper.emitted('input-error')).toHaveLength(3);
|
|
499
|
+
});
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
// Test complex scenarios
|
|
503
|
+
describe('Complex Scenarios', () => {
|
|
504
|
+
it('works with all props combined', () => {
|
|
505
|
+
const wrapper = mount(Checkbox, {
|
|
506
|
+
props: {
|
|
507
|
+
label: 'Complex checkbox',
|
|
508
|
+
success: false,
|
|
509
|
+
error: true,
|
|
510
|
+
disabled: false,
|
|
511
|
+
value: 'complex-value',
|
|
512
|
+
modelValue: ['other-value', 'complex-value'],
|
|
513
|
+
density: 'comfortable'
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
expect(wrapper.vm.isChecked).toBe(true);
|
|
518
|
+
expect(wrapper.find('.label-error').exists()).toBe(true);
|
|
519
|
+
expect(wrapper.find('.density-comfortable').exists()).toBe(true);
|
|
520
|
+
expect(wrapper.text()).toBe('Complex checkbox');
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
it('handles switching between array and boolean modelValue types', async () => {
|
|
524
|
+
const wrapper = mount(Checkbox, {
|
|
525
|
+
props: {
|
|
526
|
+
modelValue: [],
|
|
527
|
+
value: 'test'
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
expect(wrapper.vm.isChecked).toBe(false);
|
|
532
|
+
|
|
533
|
+
// Switch to boolean
|
|
534
|
+
await wrapper.setProps({ modelValue: true });
|
|
535
|
+
expect(wrapper.vm.isChecked).toBe(true);
|
|
536
|
+
|
|
537
|
+
// Switch back to array
|
|
538
|
+
await wrapper.setProps({ modelValue: ['test'] });
|
|
539
|
+
expect(wrapper.vm.isChecked).toBe(true);
|
|
540
|
+
|
|
541
|
+
await wrapper.setProps({ modelValue: [] });
|
|
542
|
+
expect(wrapper.vm.isChecked).toBe(false);
|
|
543
|
+
});
|
|
544
|
+
});
|
|
545
545
|
});
|