@zap-wunschlachen/wl-shared-components 1.0.76 → 1.0.78
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 +229 -229
- package/.github/workflows/static.yml +61 -61
- package/.github/workflows/update-snapshots.yml +37 -37
- package/.prettierrc.json +8 -8
- 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 +139 -139
- package/README.md +56 -56
- package/docs/assets.md +62 -62
- package/heroicons.ts +75 -75
- package/index.html +19 -19
- package/package.json +71 -71
- 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/scripts/check-translations.ts +352 -352
- package/src/assets/css/base.css +242 -242
- package/src/assets/css/variables.css +176 -176
- package/src/components/Accordion/Accordion.css +65 -65
- package/src/components/Accordion/AccordionGroup.vue +88 -88
- package/src/components/Accordion/AccordionItem.vue +272 -272
- package/src/components/Accordion/presets/default.css +4 -4
- package/src/components/Accordion/presets/elevated.css +25 -25
- package/src/components/Accordion/presets/filled.css +26 -26
- package/src/components/Accordion/presets/index.css +5 -5
- package/src/components/Accordion/presets/plain.css +34 -34
- 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 +20 -20
- package/src/components/Appointment/Card/AnamneseNotification.vue +23 -23
- package/src/components/Appointment/Card/Card.css +99 -99
- package/src/components/Appointment/Card/Card.vue +97 -97
- package/src/components/Appointment/Card/Details.css +62 -62
- package/src/components/Appointment/Card/Details.vue +44 -44
- package/src/components/Audio/Audio.vue +187 -187
- package/src/components/Audio/Waveform.vue +118 -118
- package/src/components/Banner/Banner.css +29 -29
- package/src/components/Banner/Banner.vue +89 -89
- package/src/components/Button/Button.vue +257 -257
- package/src/components/CheckBox/CheckBox.css +234 -234
- package/src/components/CheckBox/Checkbox.vue +184 -184
- package/src/components/DateInput/DateInput.css +2 -2
- package/src/components/DateInput/DateInput.vue +376 -370
- package/src/components/Dialog/Dialog.css +6 -6
- package/src/components/Dialog/Dialog.vue +46 -46
- package/src/components/EditField/EditField.css +19 -19
- package/src/components/EditField/EditField.vue +211 -211
- package/src/components/ErrorPage/ErrorPage.css +172 -172
- package/src/components/IconBullet/IconBullet.vue +104 -104
- package/src/components/IconBullet/IconBulletList.vue +55 -55
- package/src/components/Icons/AdvanceAppointments.vue +161 -161
- package/src/components/Icons/Audio/CloudFailed.vue +27 -27
- package/src/components/Icons/Audio/CloudSaved.vue +28 -28
- package/src/components/Icons/Audio/Delete.vue +22 -22
- package/src/components/Icons/Audio/Pause.vue +25 -25
- package/src/components/Icons/Audio/Play.vue +22 -22
- package/src/components/Icons/Calendar.vue +28 -28
- package/src/components/Icons/CalendarNotification.vue +137 -137
- package/src/components/Icons/Chair.vue +43 -43
- package/src/components/Icons/ChairNotification.vue +46 -46
- package/src/components/Icons/Circle.vue +66 -66
- package/src/components/Icons/FavIcon.vue +69 -69
- package/src/components/Icons/FilledCircle.vue +11 -11
- package/src/components/Icons/Group3.vue +57 -57
- package/src/components/Icons/Play.vue +16 -16
- package/src/components/Icons/RingNotification.vue +65 -65
- package/src/components/Icons/SolidArrowRight.vue +14 -14
- package/src/components/Icons/checkbox.vue +19 -19
- package/src/components/Icons/outlineChecked.vue +38 -38
- package/src/components/Input/Input.css +234 -234
- package/src/components/Input/Input.vue +281 -281
- 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 +78 -78
- package/src/components/MaintenanceBanner/MaintenanceBanner.css +353 -353
- package/src/components/MaintenanceBanner/MaintenanceBanner.vue +140 -140
- package/src/components/MaintenanceBanner/MaintenanceIllustration.vue +54 -54
- package/src/components/Modal/Modal.css +5 -5
- package/src/components/Modal/Modal.vue +29 -29
- package/src/components/NotificationBubble/NotificationBubble.css +4 -4
- package/src/components/NotificationBubble/NotificationBubble.vue +90 -90
- package/src/components/OtpInput/OtpInput.css +43 -43
- package/src/components/OtpInput/OtpInput.vue +181 -181
- package/src/components/PhoneInput/PhoneInput.css +151 -126
- package/src/components/PhoneInput/PhoneInput.vue +230 -139
- package/src/components/RadioGroup/RadioGroup.css +65 -0
- package/src/components/RadioGroup/RadioGroup.vue +134 -0
- package/src/components/Select/Select.css +172 -172
- package/src/components/Select/Select.vue +377 -377
- package/src/components/SelectAutocomplete/SelectAutocomplete.css +172 -172
- package/src/components/SelectAutocomplete/SelectAutocomplete.vue +414 -414
- package/src/components/TextArea/TextArea.css +269 -269
- package/src/components/TextArea/TextArea.vue +207 -207
- package/src/components/TickBox/TickBox.css +116 -116
- package/src/components/TickBox/TickBox.vue +172 -172
- package/src/components/Tile/Tile.css +106 -106
- package/src/components/Tile/Tile.vue +173 -173
- package/src/components/accessibility.css +218 -218
- package/src/components/index.ts +110 -109
- 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 +43 -43
- package/src/main.ts +11 -11
- package/src/pages/AccordionGroupPage.vue +873 -873
- package/src/pages/AllPage.vue +2483 -2365
- package/src/pages/SelectPage.vue +1302 -1302
- package/src/pages/TilePage.vue +902 -902
- package/src/plugins/vuetify.ts +54 -54
- package/src/shims-vue.d.ts +30 -30
- package/src/utils/index.ts +733 -733
- package/src/vite-env.d.ts +1 -1
- package/tests/unit/accessibility/component-a11y.spec.ts +657 -657
- package/tests/unit/components/Accordion/AccordionGroup.spec.ts +228 -228
- package/tests/unit/components/Accordion/AccordionItem.spec.ts +257 -257
- package/tests/unit/components/Appointment/AnamneseNotification.spec.ts +176 -176
- package/tests/unit/components/Appointment/Card/Actions.spec.ts +436 -436
- package/tests/unit/components/Appointment/Card/Card.spec.ts +531 -531
- package/tests/unit/components/Appointment/Card/Details.spec.ts +395 -395
- 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/AnamneseAnswerDialog.spec.ts +344 -0
- package/tests/unit/components/Core/Banner.spec.ts +187 -0
- package/tests/unit/components/Core/Button.spec.ts +346 -346
- package/tests/unit/components/Core/Checkbox.spec.ts +544 -544
- package/tests/unit/components/Core/DateInput.spec.ts +702 -702
- package/tests/unit/components/Core/Dialog.spec.ts +448 -448
- package/tests/unit/components/Core/EditField.spec.ts +541 -541
- package/tests/unit/components/Core/Input.spec.ts +512 -512
- package/tests/unit/components/Core/List.spec.ts +163 -0
- package/tests/unit/components/Core/ListItem.spec.ts +205 -0
- 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 +757 -619
- package/tests/unit/components/Core/RadioGroup.spec.ts +318 -0
- package/tests/unit/components/Core/Select.spec.ts +712 -712
- package/tests/unit/components/Core/SelectAutocomplete.spec.ts +361 -0
- package/tests/unit/components/Core/TextArea.spec.ts +565 -565
- package/tests/unit/components/Core/TickBox.spec.ts +836 -836
- package/tests/unit/components/Core/Tile.spec.ts +286 -0
- package/tests/unit/components/DateInput/DateInput.spec.ts +128 -0
- 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 +186 -186
- 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 +193 -193
- package/tests/unit/components/Icons/Chair.spec.ts +241 -241
- package/tests/unit/components/Icons/ChairNotification.spec.ts +318 -318
- package/tests/unit/components/Icons/Circle.spec.ts +255 -255
- package/tests/unit/components/Icons/FavIcon.spec.ts +259 -259
- package/tests/unit/components/Icons/FilledCircle.spec.ts +274 -274
- package/tests/unit/components/Icons/Group3.spec.ts +362 -362
- package/tests/unit/components/Icons/Logo.spec.ts +229 -229
- package/tests/unit/components/Icons/MiniLogo.spec.ts +38 -38
- package/tests/unit/components/Icons/RingNotification.spec.ts +400 -400
- package/tests/unit/components/Icons/SolidArrowRight.spec.ts +49 -49
- package/tests/unit/components/Icons/calendar.spec.ts +293 -293
- package/tests/unit/components/Icons/checkbox.spec.ts +315 -315
- package/tests/unit/components/Icons/outlineChecked.spec.ts +441 -441
- package/tests/unit/components/Icons/play.spec.ts +315 -315
- 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 +182 -182
- package/tests/unit/setup.ts +237 -237
- 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 +111 -111
- package/tests/unit/utils/accessibility.spec.ts +318 -318
- package/tests/unit/utils/anamnese.spec.ts +531 -0
- package/tsconfig.json +26 -26
- package/vite.config.ts +29 -29
- package/vitest.config.ts +91 -91
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import { nextTick } from 'vue';
|
|
4
|
+
import SelectAutocomplete from '@components/SelectAutocomplete/SelectAutocomplete.vue';
|
|
5
|
+
|
|
6
|
+
// Add v-autocomplete stub for this test
|
|
7
|
+
const vAutocompleteStub = {
|
|
8
|
+
name: 'v-autocomplete',
|
|
9
|
+
template: `<div class="v-autocomplete" data-testid="root" :aria-label="ariaLabel" :aria-invalid="ariaInvalid" :aria-describedby="ariaDescribedby">
|
|
10
|
+
<input data-testid="autocomplete-input" />
|
|
11
|
+
<slot name="menu" />
|
|
12
|
+
<slot name="item" />
|
|
13
|
+
<slot name="selection" />
|
|
14
|
+
<slot name="no-data" />
|
|
15
|
+
<slot name="prepend" />
|
|
16
|
+
<slot name="prepend-inner" />
|
|
17
|
+
<slot name="append" />
|
|
18
|
+
<slot name="append-inner" />
|
|
19
|
+
</div>`,
|
|
20
|
+
props: [
|
|
21
|
+
'modelValue', 'items', 'disabled', 'error', 'label', 'clearable', 'chips',
|
|
22
|
+
'multiple', 'variant', 'density', 'returnObject', 'itemTitle', 'itemValue',
|
|
23
|
+
'placeholder', 'persistentPlaceholder', 'appendIcon', 'appendInnerIcon',
|
|
24
|
+
'prependIcon', 'prependInnerIcon', 'menuIcon', 'clearIcon', 'closableChips',
|
|
25
|
+
'autoSelectFirst', 'customFilter', 'hideNoData', 'hideDetails', 'ariaLabel',
|
|
26
|
+
'ariaInvalid', 'ariaDescribedby', 'menuProps', 'rounded', 'rules',
|
|
27
|
+
],
|
|
28
|
+
emits: [
|
|
29
|
+
'update:modelValue', 'click:append', 'click:append-inner',
|
|
30
|
+
'click:clear', 'click:prepend', 'click:prepend-inner', 'update:search',
|
|
31
|
+
],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const mountSelect = (props: Record<string, any> = {}, options: Record<string, any> = {}) => {
|
|
35
|
+
return mount(SelectAutocomplete, {
|
|
36
|
+
props,
|
|
37
|
+
global: {
|
|
38
|
+
stubs: {
|
|
39
|
+
'v-autocomplete': vAutocompleteStub,
|
|
40
|
+
},
|
|
41
|
+
...options?.global,
|
|
42
|
+
},
|
|
43
|
+
...options,
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
describe('SelectAutocomplete', () => {
|
|
48
|
+
beforeEach(() => {
|
|
49
|
+
vi.clearAllMocks();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// ─── Default Rendering ────────────────────────────────────────────
|
|
53
|
+
describe('Default Rendering', () => {
|
|
54
|
+
it('renders with data-testid="root"', () => {
|
|
55
|
+
const wrapper = mountSelect();
|
|
56
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('applies wl-select CSS class', () => {
|
|
60
|
+
const wrapper = mountSelect();
|
|
61
|
+
expect(wrapper.find('.wl-select').exists()).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('wraps in v-autocomplete', () => {
|
|
65
|
+
const wrapper = mountSelect();
|
|
66
|
+
expect(wrapper.findComponent({ name: 'v-autocomplete' }).exists()).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// ─── Default Props ────────────────────────────────────────────────
|
|
71
|
+
describe('Default Props', () => {
|
|
72
|
+
it('defaults label to "Label"', () => {
|
|
73
|
+
const wrapper = mountSelect();
|
|
74
|
+
expect(wrapper.vm.label).toBe('Label');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('defaults density to "compact"', () => {
|
|
78
|
+
const wrapper = mountSelect();
|
|
79
|
+
expect(wrapper.vm.density).toBe('compact');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('defaults variant to "outlined"', () => {
|
|
83
|
+
const wrapper = mountSelect();
|
|
84
|
+
expect(wrapper.vm.variant).toBe('outlined');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('defaults disabled to false', () => {
|
|
88
|
+
const wrapper = mountSelect();
|
|
89
|
+
expect(wrapper.vm.disabled).toBe(false);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('defaults error to false', () => {
|
|
93
|
+
const wrapper = mountSelect();
|
|
94
|
+
expect(wrapper.vm.error).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('defaults clearable to false', () => {
|
|
98
|
+
const wrapper = mountSelect();
|
|
99
|
+
expect(wrapper.vm.clearable).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('defaults returnObject to true', () => {
|
|
103
|
+
const wrapper = mountSelect();
|
|
104
|
+
expect(wrapper.vm.returnObject).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('defaults hideDetails to true', () => {
|
|
108
|
+
const wrapper = mountSelect();
|
|
109
|
+
expect(wrapper.vm.hideDetails).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('defaults items to empty array', () => {
|
|
113
|
+
const wrapper = mountSelect();
|
|
114
|
+
expect(wrapper.vm.items).toEqual([]);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// ─── v-model ──────────────────────────────────────────────────────
|
|
119
|
+
describe('v-model', () => {
|
|
120
|
+
it('accepts modelValue prop', () => {
|
|
121
|
+
const wrapper = mountSelect({ modelValue: 'test' });
|
|
122
|
+
expect(wrapper.vm.modelValue).toBe('test');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('emits update:modelValue when internal value changes', async () => {
|
|
126
|
+
const wrapper = mountSelect({ modelValue: 'a' });
|
|
127
|
+
// Trigger internal value change
|
|
128
|
+
(wrapper.vm as any).internalValue = 'b';
|
|
129
|
+
await nextTick();
|
|
130
|
+
expect(wrapper.emitted('update:modelValue')).toBeTruthy();
|
|
131
|
+
expect(wrapper.emitted('update:modelValue')![0]).toEqual(['b']);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('syncs external modelValue changes', async () => {
|
|
135
|
+
const wrapper = mountSelect({ modelValue: 'x' });
|
|
136
|
+
await wrapper.setProps({ modelValue: 'y' });
|
|
137
|
+
expect((wrapper.vm as any).internalValue).toBe('y');
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('handles array modelValue for multiple mode', () => {
|
|
141
|
+
const wrapper = mountSelect({
|
|
142
|
+
modelValue: ['a', 'b'],
|
|
143
|
+
multiple: true,
|
|
144
|
+
});
|
|
145
|
+
expect(wrapper.vm.modelValue).toEqual(['a', 'b']);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// ─── Event Emission ───────────────────────────────────────────────
|
|
150
|
+
describe('Event Emission', () => {
|
|
151
|
+
it('emits click:append', () => {
|
|
152
|
+
const wrapper = mountSelect();
|
|
153
|
+
const autocomplete = wrapper.findComponent({ name: 'v-autocomplete' });
|
|
154
|
+
autocomplete.vm.$emit('click:append', new MouseEvent('click'));
|
|
155
|
+
expect(wrapper.emitted('click:append')).toBeTruthy();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('emits click:appendInner', () => {
|
|
159
|
+
const wrapper = mountSelect();
|
|
160
|
+
const autocomplete = wrapper.findComponent({ name: 'v-autocomplete' });
|
|
161
|
+
autocomplete.vm.$emit('click:append-inner', new MouseEvent('click'));
|
|
162
|
+
expect(wrapper.emitted('click:appendInner')).toBeTruthy();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('emits click:clear', () => {
|
|
166
|
+
const wrapper = mountSelect();
|
|
167
|
+
const autocomplete = wrapper.findComponent({ name: 'v-autocomplete' });
|
|
168
|
+
autocomplete.vm.$emit('click:clear', new MouseEvent('click'));
|
|
169
|
+
expect(wrapper.emitted('click:clear')).toBeTruthy();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('emits click:prepend', () => {
|
|
173
|
+
const wrapper = mountSelect();
|
|
174
|
+
const autocomplete = wrapper.findComponent({ name: 'v-autocomplete' });
|
|
175
|
+
autocomplete.vm.$emit('click:prepend', new MouseEvent('click'));
|
|
176
|
+
expect(wrapper.emitted('click:prepend')).toBeTruthy();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('emits click:prependInner', () => {
|
|
180
|
+
const wrapper = mountSelect();
|
|
181
|
+
const autocomplete = wrapper.findComponent({ name: 'v-autocomplete' });
|
|
182
|
+
autocomplete.vm.$emit('click:prepend-inner', new MouseEvent('click'));
|
|
183
|
+
expect(wrapper.emitted('click:prependInner')).toBeTruthy();
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('emits update:search', () => {
|
|
187
|
+
const wrapper = mountSelect();
|
|
188
|
+
const autocomplete = wrapper.findComponent({ name: 'v-autocomplete' });
|
|
189
|
+
autocomplete.vm.$emit('update:search', 'query');
|
|
190
|
+
expect(wrapper.emitted('update:search')).toBeTruthy();
|
|
191
|
+
expect(wrapper.emitted('update:search')![0]).toEqual(['query']);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// ─── Items & Filtering ────────────────────────────────────────────
|
|
196
|
+
describe('Items & Filtering', () => {
|
|
197
|
+
it('passes items to v-autocomplete', () => {
|
|
198
|
+
const items = [
|
|
199
|
+
{ title: 'Item 1', value: '1' },
|
|
200
|
+
{ title: 'Item 2', value: '2' },
|
|
201
|
+
];
|
|
202
|
+
const wrapper = mountSelect({ items });
|
|
203
|
+
expect(wrapper.vm.items).toEqual(items);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('passes customFilter function', () => {
|
|
207
|
+
const filter = vi.fn();
|
|
208
|
+
const wrapper = mountSelect({ customFilter: filter });
|
|
209
|
+
expect(wrapper.vm.customFilter).toBe(filter);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('passes autoSelectFirst', () => {
|
|
213
|
+
const wrapper = mountSelect({ autoSelectFirst: true });
|
|
214
|
+
expect(wrapper.vm.autoSelectFirst).toBe(true);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('passes hideNoData', () => {
|
|
218
|
+
const wrapper = mountSelect({ hideNoData: true });
|
|
219
|
+
expect(wrapper.vm.hideNoData).toBe(true);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// ─── Slots ────────────────────────────────────────────────────────
|
|
224
|
+
describe('Slots', () => {
|
|
225
|
+
it('renders menu slot', () => {
|
|
226
|
+
const wrapper = mountSelect({}, {
|
|
227
|
+
slots: { menu: '<div class="custom-menu">Menu</div>' },
|
|
228
|
+
});
|
|
229
|
+
expect(wrapper.find('.custom-menu').exists()).toBe(true);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('renders prepend slot', () => {
|
|
233
|
+
const wrapper = mountSelect({}, {
|
|
234
|
+
slots: { prepend: '<div class="custom-prepend">P</div>' },
|
|
235
|
+
});
|
|
236
|
+
expect(wrapper.find('.custom-prepend').exists()).toBe(true);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('renders append slot', () => {
|
|
240
|
+
const wrapper = mountSelect({}, {
|
|
241
|
+
slots: { append: '<div class="custom-append">A</div>' },
|
|
242
|
+
});
|
|
243
|
+
expect(wrapper.find('.custom-append').exists()).toBe(true);
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// ─── Exposed Methods ──────────────────────────────────────────────
|
|
248
|
+
describe('Exposed Methods', () => {
|
|
249
|
+
it('exposes focus method', () => {
|
|
250
|
+
const wrapper = mountSelect();
|
|
251
|
+
expect(typeof wrapper.vm.focus).toBe('function');
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('exposes blur method', () => {
|
|
255
|
+
const wrapper = mountSelect();
|
|
256
|
+
expect(typeof wrapper.vm.blur).toBe('function');
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('exposes select method', () => {
|
|
260
|
+
const wrapper = mountSelect();
|
|
261
|
+
expect(typeof wrapper.vm.select).toBe('function');
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// ─── borderOnHover ────────────────────────────────────────────────
|
|
266
|
+
describe('borderOnHover', () => {
|
|
267
|
+
it('does not add border-on-hover class by default', () => {
|
|
268
|
+
const wrapper = mountSelect();
|
|
269
|
+
expect(wrapper.find('.border-on-hover').exists()).toBe(false);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('adds border-on-hover class when prop is true', () => {
|
|
273
|
+
const wrapper = mountSelect({ borderOnHover: true });
|
|
274
|
+
expect(wrapper.find('.border-on-hover').exists()).toBe(true);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// ─── Theme Colors ─────────────────────────────────────────────────
|
|
279
|
+
describe('Theme Colors', () => {
|
|
280
|
+
it('uses siteColors by default', () => {
|
|
281
|
+
const wrapper = mountSelect();
|
|
282
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it('uses injected themeColors when provided', () => {
|
|
286
|
+
const themeColors = {
|
|
287
|
+
value: {
|
|
288
|
+
select_item_text: '#111',
|
|
289
|
+
select_item_default_bg: '#222',
|
|
290
|
+
select_item_hovered_bg: '#333',
|
|
291
|
+
select_item_selected_left_border: '#444',
|
|
292
|
+
select_item_selected_bg: '#555',
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
const wrapper = mount(SelectAutocomplete, {
|
|
296
|
+
global: {
|
|
297
|
+
provide: { themeColors },
|
|
298
|
+
stubs: { 'v-autocomplete': vAutocompleteStub },
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// ─── WCAG Accessibility ───────────────────────────────────────────
|
|
306
|
+
describe('WCAG Accessibility', () => {
|
|
307
|
+
it('sets aria-label when provided (WCAG 4.1.2)', () => {
|
|
308
|
+
const wrapper = mountSelect({ ariaLabel: 'Select a patient' });
|
|
309
|
+
const autocomplete = wrapper.findComponent({ name: 'v-autocomplete' });
|
|
310
|
+
expect(autocomplete.props('ariaLabel')).toBe('Select a patient');
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('does not set aria-label when not provided', () => {
|
|
314
|
+
const wrapper = mountSelect();
|
|
315
|
+
const autocomplete = wrapper.findComponent({ name: 'v-autocomplete' });
|
|
316
|
+
expect(autocomplete.props('ariaLabel')).toBeUndefined();
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('sets aria-invalid when error is true', () => {
|
|
320
|
+
const wrapper = mountSelect({ error: true });
|
|
321
|
+
const autocomplete = wrapper.findComponent({ name: 'v-autocomplete' });
|
|
322
|
+
expect(autocomplete.props('ariaInvalid')).toBe(true);
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
it('does not set aria-invalid when no error', () => {
|
|
326
|
+
const wrapper = mountSelect({ error: false });
|
|
327
|
+
const autocomplete = wrapper.findComponent({ name: 'v-autocomplete' });
|
|
328
|
+
expect(autocomplete.props('ariaInvalid')).toBeUndefined();
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('sets aria-describedby when provided (WCAG 1.3.1)', () => {
|
|
332
|
+
const wrapper = mountSelect({ ariaDescribedby: 'error-msg' });
|
|
333
|
+
const autocomplete = wrapper.findComponent({ name: 'v-autocomplete' });
|
|
334
|
+
expect(autocomplete.props('ariaDescribedby')).toBe('error-msg');
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it('does not set aria-describedby when not provided', () => {
|
|
338
|
+
const wrapper = mountSelect();
|
|
339
|
+
const autocomplete = wrapper.findComponent({ name: 'v-autocomplete' });
|
|
340
|
+
expect(autocomplete.props('ariaDescribedby')).toBeUndefined();
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// ─── Edge Cases ───────────────────────────────────────────────────
|
|
345
|
+
describe('Edge Cases', () => {
|
|
346
|
+
it('handles empty items', () => {
|
|
347
|
+
const wrapper = mountSelect({ items: [] });
|
|
348
|
+
expect(wrapper.vm.items).toEqual([]);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it('handles disabled state', () => {
|
|
352
|
+
const wrapper = mountSelect({ disabled: true });
|
|
353
|
+
expect(wrapper.vm.disabled).toBe(true);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it('handles undefined modelValue', () => {
|
|
357
|
+
const wrapper = mountSelect();
|
|
358
|
+
expect(wrapper.vm.modelValue).toBeUndefined();
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
});
|