@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,607 +1,607 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { mount } from '@vue/test-utils';
|
|
3
|
-
import NotificationBubble from '@components/NotificationBubble/NotificationBubble.vue';
|
|
4
|
-
|
|
5
|
-
describe('NotificationBubble', () => {
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
vi.clearAllMocks();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
// Test default behavior and rendering
|
|
11
|
-
describe('Default Behavior', () => {
|
|
12
|
-
it('renders with default props', () => {
|
|
13
|
-
const wrapper = mount(NotificationBubble);
|
|
14
|
-
|
|
15
|
-
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
16
|
-
expect(wrapper.find('.notification-bubble').exists()).toBe(true);
|
|
17
|
-
expect(wrapper.vm.color).toBe('');
|
|
18
|
-
expect(wrapper.vm.size).toBe('30');
|
|
19
|
-
expect(wrapper.vm.textColor).toBe('var(--Dental-Blue-0)');
|
|
20
|
-
expect(wrapper.vm.iconSize).toBe('20');
|
|
21
|
-
expect(wrapper.vm.readonly).toBe(false);
|
|
22
|
-
expect(wrapper.vm.variant).toBe('flat');
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('has data-testid for testing', () => {
|
|
26
|
-
const wrapper = mount(NotificationBubble);
|
|
27
|
-
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('applies notification-bubble CSS class', () => {
|
|
31
|
-
const wrapper = mount(NotificationBubble);
|
|
32
|
-
expect(wrapper.find('.notification-bubble').exists()).toBe(true);
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
// Test text display
|
|
37
|
-
describe('Text Display', () => {
|
|
38
|
-
it('displays text when text prop is provided', () => {
|
|
39
|
-
const wrapper = mount(NotificationBubble, {
|
|
40
|
-
props: {
|
|
41
|
-
text: 'Test Notification'
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
expect(wrapper.find('h4').exists()).toBe(true);
|
|
46
|
-
expect(wrapper.find('h4').text()).toBe('Test Notification');
|
|
47
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(false);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('applies text color to text element', () => {
|
|
51
|
-
const wrapper = mount(NotificationBubble, {
|
|
52
|
-
props: {
|
|
53
|
-
text: 'Colored Text',
|
|
54
|
-
textColor: '#FF0000'
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const h4Element = wrapper.find('h4');
|
|
59
|
-
expect(h4Element.exists()).toBe(true);
|
|
60
|
-
// The style would be applied by Vue's style binding
|
|
61
|
-
expect(h4Element.text()).toBe('Colored Text');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('handles empty text', () => {
|
|
65
|
-
const wrapper = mount(NotificationBubble, {
|
|
66
|
-
props: {
|
|
67
|
-
text: ''
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Empty string is falsy for v-if="text", so h4 should not exist
|
|
72
|
-
expect(wrapper.find('h4').exists()).toBe(false);
|
|
73
|
-
// Instead, it should render the icon
|
|
74
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('handles long text', () => {
|
|
78
|
-
const longText = 'This is a very long notification text that might wrap or overflow depending on the container size and styling';
|
|
79
|
-
const wrapper = mount(NotificationBubble, {
|
|
80
|
-
props: {
|
|
81
|
-
text: longText
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
expect(wrapper.find('h4').text()).toBe(longText);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it('handles special characters in text', () => {
|
|
89
|
-
const specialText = 'Notification: !@#$%^&*()_+ ñáéíóú ≈≠≤≥';
|
|
90
|
-
const wrapper = mount(NotificationBubble, {
|
|
91
|
-
props: {
|
|
92
|
-
text: specialText
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
expect(wrapper.find('h4').text()).toBe(specialText);
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// Test icon display
|
|
101
|
-
describe('Icon Display', () => {
|
|
102
|
-
it('displays icon when text prop is not provided', () => {
|
|
103
|
-
const wrapper = mount(NotificationBubble, {
|
|
104
|
-
props: {
|
|
105
|
-
icon: 'mdi-bell'
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
110
|
-
expect(wrapper.find('h4').exists()).toBe(false);
|
|
111
|
-
expect(wrapper.vm.icon).toBe('mdi-bell');
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('displays icon when text is undefined', () => {
|
|
115
|
-
const wrapper = mount(NotificationBubble, {
|
|
116
|
-
props: {
|
|
117
|
-
text: undefined,
|
|
118
|
-
icon: 'mdi-notification'
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
123
|
-
expect(wrapper.find('h4').exists()).toBe(false);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('prioritizes text over icon when both are provided', () => {
|
|
127
|
-
const wrapper = mount(NotificationBubble, {
|
|
128
|
-
props: {
|
|
129
|
-
text: 'Text Priority',
|
|
130
|
-
icon: 'mdi-bell'
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
expect(wrapper.find('h4').exists()).toBe(true);
|
|
135
|
-
expect(wrapper.find('h4').text()).toBe('Text Priority');
|
|
136
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(false);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it('applies icon size', () => {
|
|
140
|
-
const wrapper = mount(NotificationBubble, {
|
|
141
|
-
props: {
|
|
142
|
-
icon: 'mdi-bell',
|
|
143
|
-
iconSize: '24'
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
expect(wrapper.vm.iconSize).toBe('24');
|
|
148
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('applies icon color', () => {
|
|
152
|
-
const wrapper = mount(NotificationBubble, {
|
|
153
|
-
props: {
|
|
154
|
-
icon: 'mdi-bell',
|
|
155
|
-
textColor: '#00FF00'
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
expect(wrapper.vm.textColor).toBe('#00FF00');
|
|
160
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('handles different icon names', () => {
|
|
164
|
-
const icons = [
|
|
165
|
-
'mdi-bell',
|
|
166
|
-
'heroicons:bell',
|
|
167
|
-
'fa-solid:bell',
|
|
168
|
-
'custom-icon'
|
|
169
|
-
];
|
|
170
|
-
|
|
171
|
-
icons.forEach(iconName => {
|
|
172
|
-
const wrapper = mount(NotificationBubble, {
|
|
173
|
-
props: {
|
|
174
|
-
icon: iconName
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
expect(wrapper.vm.icon).toBe(iconName);
|
|
179
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
// Test color properties
|
|
185
|
-
describe('Color Properties', () => {
|
|
186
|
-
it('uses default text color', () => {
|
|
187
|
-
const wrapper = mount(NotificationBubble);
|
|
188
|
-
expect(wrapper.vm.textColor).toBe('var(--Dental-Blue-0)');
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
it('accepts custom text color', () => {
|
|
192
|
-
const wrapper = mount(NotificationBubble, {
|
|
193
|
-
props: {
|
|
194
|
-
textColor: '#FF5722'
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
expect(wrapper.vm.textColor).toBe('#FF5722');
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
it('uses default empty background color', () => {
|
|
202
|
-
const wrapper = mount(NotificationBubble);
|
|
203
|
-
expect(wrapper.vm.color).toBe('');
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
it('accepts custom background color', () => {
|
|
207
|
-
const wrapper = mount(NotificationBubble, {
|
|
208
|
-
props: {
|
|
209
|
-
color: '#E3F2FD'
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
expect(wrapper.vm.color).toBe('#E3F2FD');
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it('handles CSS color formats', () => {
|
|
217
|
-
const colorFormats = [
|
|
218
|
-
'#FF0000',
|
|
219
|
-
'rgb(255, 0, 0)',
|
|
220
|
-
'rgba(255, 0, 0, 0.5)',
|
|
221
|
-
'hsl(0, 100%, 50%)',
|
|
222
|
-
'red',
|
|
223
|
-
'var(--custom-color)'
|
|
224
|
-
];
|
|
225
|
-
|
|
226
|
-
colorFormats.forEach(color => {
|
|
227
|
-
const wrapper = mount(NotificationBubble, {
|
|
228
|
-
props: {
|
|
229
|
-
color,
|
|
230
|
-
textColor: color
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
expect(wrapper.vm.color).toBe(color);
|
|
235
|
-
expect(wrapper.vm.textColor).toBe(color);
|
|
236
|
-
});
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
// Test size properties
|
|
241
|
-
describe('Size Properties', () => {
|
|
242
|
-
it('uses default size', () => {
|
|
243
|
-
const wrapper = mount(NotificationBubble);
|
|
244
|
-
expect(wrapper.vm.size).toBe('30');
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('accepts string size', () => {
|
|
248
|
-
const wrapper = mount(NotificationBubble, {
|
|
249
|
-
props: {
|
|
250
|
-
size: '40'
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
expect(wrapper.vm.size).toBe('40');
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
it('accepts number size', () => {
|
|
258
|
-
const wrapper = mount(NotificationBubble, {
|
|
259
|
-
props: {
|
|
260
|
-
size: 50
|
|
261
|
-
}
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
expect(wrapper.vm.size).toBe(50);
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it('uses default icon size', () => {
|
|
268
|
-
const wrapper = mount(NotificationBubble);
|
|
269
|
-
expect(wrapper.vm.iconSize).toBe('20');
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
it('accepts custom icon size', () => {
|
|
273
|
-
const wrapper = mount(NotificationBubble, {
|
|
274
|
-
props: {
|
|
275
|
-
iconSize: '32'
|
|
276
|
-
}
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
expect(wrapper.vm.iconSize).toBe('32');
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it('handles different size values', () => {
|
|
283
|
-
const sizes = ['16', '24', '32', '48', '64'];
|
|
284
|
-
|
|
285
|
-
sizes.forEach(size => {
|
|
286
|
-
const wrapper = mount(NotificationBubble, {
|
|
287
|
-
props: {
|
|
288
|
-
size,
|
|
289
|
-
iconSize: size
|
|
290
|
-
}
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
expect(wrapper.vm.size).toBe(size);
|
|
294
|
-
expect(wrapper.vm.iconSize).toBe(size);
|
|
295
|
-
});
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
// Test state properties
|
|
300
|
-
describe('State Properties', () => {
|
|
301
|
-
it('uses default readonly state', () => {
|
|
302
|
-
const wrapper = mount(NotificationBubble);
|
|
303
|
-
expect(wrapper.vm.readonly).toBe(false);
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
it('accepts readonly true', () => {
|
|
307
|
-
const wrapper = mount(NotificationBubble, {
|
|
308
|
-
props: {
|
|
309
|
-
readonly: true
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
expect(wrapper.vm.readonly).toBe(true);
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
it('uses default variant', () => {
|
|
317
|
-
const wrapper = mount(NotificationBubble);
|
|
318
|
-
expect(wrapper.vm.variant).toBe('flat');
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
it('accepts custom variant', () => {
|
|
322
|
-
const variants = ['flat', 'outlined', 'contained', 'tonal', 'text'];
|
|
323
|
-
|
|
324
|
-
variants.forEach(variant => {
|
|
325
|
-
const wrapper = mount(NotificationBubble, {
|
|
326
|
-
props: { variant }
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
expect(wrapper.vm.variant).toBe(variant);
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
// Test Vuetify integration
|
|
335
|
-
describe('Vuetify Integration', () => {
|
|
336
|
-
it('applies Vuetify button props correctly', () => {
|
|
337
|
-
const wrapper = mount(NotificationBubble, {
|
|
338
|
-
props: {
|
|
339
|
-
color: '#2196F3',
|
|
340
|
-
size: 40,
|
|
341
|
-
variant: 'outlined',
|
|
342
|
-
readonly: true
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
347
|
-
expect(wrapper.vm.color).toBe('#2196F3');
|
|
348
|
-
expect(wrapper.vm.size).toBe(40);
|
|
349
|
-
expect(wrapper.vm.variant).toBe('outlined');
|
|
350
|
-
expect(wrapper.vm.readonly).toBe(true);
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
it('uses fixed Vuetify props', () => {
|
|
354
|
-
const wrapper = mount(NotificationBubble);
|
|
355
|
-
|
|
356
|
-
// These props are hardcoded in the template
|
|
357
|
-
// elevation="0", flat=true, rounded="xl"
|
|
358
|
-
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
359
|
-
});
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
// Test accessibility
|
|
363
|
-
describe('Accessibility', () => {
|
|
364
|
-
it('has data-testid for testing', () => {
|
|
365
|
-
const wrapper = mount(NotificationBubble);
|
|
366
|
-
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
it('provides semantic heading for text content', () => {
|
|
370
|
-
const wrapper = mount(NotificationBubble, {
|
|
371
|
-
props: {
|
|
372
|
-
text: 'Important Notification'
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
const heading = wrapper.find('h4');
|
|
377
|
-
expect(heading.exists()).toBe(true);
|
|
378
|
-
expect(heading.text()).toBe('Important Notification');
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
it('uses icon for non-text notifications', () => {
|
|
382
|
-
const wrapper = mount(NotificationBubble, {
|
|
383
|
-
props: {
|
|
384
|
-
icon: 'mdi-alert'
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
it('maintains button semantics from v-btn', () => {
|
|
392
|
-
const wrapper = mount(NotificationBubble, {
|
|
393
|
-
props: {
|
|
394
|
-
text: 'Clickable Notification'
|
|
395
|
-
}
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
// v-btn provides button semantics
|
|
399
|
-
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
400
|
-
});
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
// Test edge cases
|
|
404
|
-
describe('Edge Cases', () => {
|
|
405
|
-
it('handles undefined text prop', () => {
|
|
406
|
-
const wrapper = mount(NotificationBubble, {
|
|
407
|
-
props: {
|
|
408
|
-
text: undefined,
|
|
409
|
-
icon: 'mdi-bell'
|
|
410
|
-
}
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
expect(wrapper.find('h4').exists()).toBe(false);
|
|
414
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
it('handles null text prop', () => {
|
|
418
|
-
const wrapper = mount(NotificationBubble, {
|
|
419
|
-
props: {
|
|
420
|
-
text: null,
|
|
421
|
-
icon: 'mdi-bell'
|
|
422
|
-
}
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
expect(wrapper.find('h4').exists()).toBe(false);
|
|
426
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
427
|
-
});
|
|
428
|
-
|
|
429
|
-
it('handles empty string text', () => {
|
|
430
|
-
const wrapper = mount(NotificationBubble, {
|
|
431
|
-
props: {
|
|
432
|
-
text: '',
|
|
433
|
-
icon: 'mdi-bell'
|
|
434
|
-
}
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
// Empty string is falsy for v-if="text", so h4 should not exist
|
|
438
|
-
expect(wrapper.find('h4').exists()).toBe(false);
|
|
439
|
-
// Icon should be rendered instead
|
|
440
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
441
|
-
});
|
|
442
|
-
|
|
443
|
-
it('handles missing icon prop when no text', () => {
|
|
444
|
-
const wrapper = mount(NotificationBubble, {
|
|
445
|
-
props: {
|
|
446
|
-
// No text, no icon
|
|
447
|
-
}
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
expect(wrapper.find('h4').exists()).toBe(false);
|
|
451
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
452
|
-
expect(wrapper.vm.icon).toBeUndefined();
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
it('handles zero size values', () => {
|
|
456
|
-
const wrapper = mount(NotificationBubble, {
|
|
457
|
-
props: {
|
|
458
|
-
size: 0,
|
|
459
|
-
iconSize: '0'
|
|
460
|
-
}
|
|
461
|
-
});
|
|
462
|
-
|
|
463
|
-
expect(wrapper.vm.size).toBe(0);
|
|
464
|
-
expect(wrapper.vm.iconSize).toBe('0');
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
it('handles very large size values', () => {
|
|
468
|
-
const wrapper = mount(NotificationBubble, {
|
|
469
|
-
props: {
|
|
470
|
-
size: 1000,
|
|
471
|
-
iconSize: '500'
|
|
472
|
-
}
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
expect(wrapper.vm.size).toBe(1000);
|
|
476
|
-
expect(wrapper.vm.iconSize).toBe('500');
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
it('handles empty string colors', () => {
|
|
480
|
-
const wrapper = mount(NotificationBubble, {
|
|
481
|
-
props: {
|
|
482
|
-
color: '',
|
|
483
|
-
textColor: ''
|
|
484
|
-
}
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
expect(wrapper.vm.color).toBe('');
|
|
488
|
-
expect(wrapper.vm.textColor).toBe('');
|
|
489
|
-
});
|
|
490
|
-
});
|
|
491
|
-
|
|
492
|
-
// Test complex scenarios
|
|
493
|
-
describe('Complex Scenarios', () => {
|
|
494
|
-
it('works with all props configured for text display', () => {
|
|
495
|
-
const wrapper = mount(NotificationBubble, {
|
|
496
|
-
props: {
|
|
497
|
-
text: 'Complete Configuration',
|
|
498
|
-
color: '#E8F5E8',
|
|
499
|
-
textColor: '#2E7D32',
|
|
500
|
-
size: 48,
|
|
501
|
-
variant: 'outlined',
|
|
502
|
-
readonly: true
|
|
503
|
-
}
|
|
504
|
-
});
|
|
505
|
-
|
|
506
|
-
expect(wrapper.vm.text).toBe('Complete Configuration');
|
|
507
|
-
expect(wrapper.vm.color).toBe('#E8F5E8');
|
|
508
|
-
expect(wrapper.vm.textColor).toBe('#2E7D32');
|
|
509
|
-
expect(wrapper.vm.size).toBe(48);
|
|
510
|
-
expect(wrapper.vm.variant).toBe('outlined');
|
|
511
|
-
expect(wrapper.vm.readonly).toBe(true);
|
|
512
|
-
expect(wrapper.find('h4').exists()).toBe(true);
|
|
513
|
-
expect(wrapper.find('h4').text()).toBe('Complete Configuration');
|
|
514
|
-
});
|
|
515
|
-
|
|
516
|
-
it('works with all props configured for icon display', () => {
|
|
517
|
-
const wrapper = mount(NotificationBubble, {
|
|
518
|
-
props: {
|
|
519
|
-
icon: 'mdi-notification-important',
|
|
520
|
-
iconSize: '28',
|
|
521
|
-
color: '#FFEBEE',
|
|
522
|
-
textColor: '#C62828',
|
|
523
|
-
size: 36,
|
|
524
|
-
variant: 'contained',
|
|
525
|
-
readonly: false
|
|
526
|
-
}
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
expect(wrapper.vm.icon).toBe('mdi-notification-important');
|
|
530
|
-
expect(wrapper.vm.iconSize).toBe('28');
|
|
531
|
-
expect(wrapper.vm.color).toBe('#FFEBEE');
|
|
532
|
-
expect(wrapper.vm.textColor).toBe('#C62828');
|
|
533
|
-
expect(wrapper.vm.size).toBe(36);
|
|
534
|
-
expect(wrapper.vm.variant).toBe('contained');
|
|
535
|
-
expect(wrapper.vm.readonly).toBe(false);
|
|
536
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
537
|
-
expect(wrapper.find('h4').exists()).toBe(false);
|
|
538
|
-
});
|
|
539
|
-
|
|
540
|
-
it('handles prop changes dynamically', async () => {
|
|
541
|
-
const wrapper = mount(NotificationBubble, {
|
|
542
|
-
props: {
|
|
543
|
-
text: 'Initial Text',
|
|
544
|
-
color: '#000000'
|
|
545
|
-
}
|
|
546
|
-
});
|
|
547
|
-
|
|
548
|
-
// Initial state
|
|
549
|
-
expect(wrapper.find('h4').exists()).toBe(true);
|
|
550
|
-
expect(wrapper.find('h4').text()).toBe('Initial Text');
|
|
551
|
-
|
|
552
|
-
// Change to icon
|
|
553
|
-
await wrapper.setProps({
|
|
554
|
-
text: undefined,
|
|
555
|
-
icon: 'mdi-bell',
|
|
556
|
-
color: '#FF0000'
|
|
557
|
-
});
|
|
558
|
-
|
|
559
|
-
expect(wrapper.find('h4').exists()).toBe(false);
|
|
560
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
561
|
-
expect(wrapper.vm.color).toBe('#FF0000');
|
|
562
|
-
|
|
563
|
-
// Change back to text
|
|
564
|
-
await wrapper.setProps({
|
|
565
|
-
text: 'Updated Text',
|
|
566
|
-
color: '#00FF00'
|
|
567
|
-
});
|
|
568
|
-
|
|
569
|
-
expect(wrapper.find('h4').exists()).toBe(true);
|
|
570
|
-
expect(wrapper.find('h4').text()).toBe('Updated Text');
|
|
571
|
-
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(false);
|
|
572
|
-
expect(wrapper.vm.color).toBe('#00FF00');
|
|
573
|
-
});
|
|
574
|
-
|
|
575
|
-
it('maintains consistent styling across different content types', () => {
|
|
576
|
-
const commonProps = {
|
|
577
|
-
color: '#F3E5F5',
|
|
578
|
-
textColor: '#7B1FA2',
|
|
579
|
-
size: 32,
|
|
580
|
-
variant: 'tonal'
|
|
581
|
-
};
|
|
582
|
-
|
|
583
|
-
// Text version
|
|
584
|
-
const textWrapper = mount(NotificationBubble, {
|
|
585
|
-
props: {
|
|
586
|
-
...commonProps,
|
|
587
|
-
text: '5'
|
|
588
|
-
}
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
// Icon version
|
|
592
|
-
const iconWrapper = mount(NotificationBubble, {
|
|
593
|
-
props: {
|
|
594
|
-
...commonProps,
|
|
595
|
-
icon: 'mdi-numeric-5',
|
|
596
|
-
iconSize: '24'
|
|
597
|
-
}
|
|
598
|
-
});
|
|
599
|
-
|
|
600
|
-
// Both should have consistent styling
|
|
601
|
-
expect(textWrapper.vm.color).toBe(iconWrapper.vm.color);
|
|
602
|
-
expect(textWrapper.vm.textColor).toBe(iconWrapper.vm.textColor);
|
|
603
|
-
expect(textWrapper.vm.size).toBe(iconWrapper.vm.size);
|
|
604
|
-
expect(textWrapper.vm.variant).toBe(iconWrapper.vm.variant);
|
|
605
|
-
});
|
|
606
|
-
});
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import NotificationBubble from '@components/NotificationBubble/NotificationBubble.vue';
|
|
4
|
+
|
|
5
|
+
describe('NotificationBubble', () => {
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
vi.clearAllMocks();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
// Test default behavior and rendering
|
|
11
|
+
describe('Default Behavior', () => {
|
|
12
|
+
it('renders with default props', () => {
|
|
13
|
+
const wrapper = mount(NotificationBubble);
|
|
14
|
+
|
|
15
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
16
|
+
expect(wrapper.find('.notification-bubble').exists()).toBe(true);
|
|
17
|
+
expect(wrapper.vm.color).toBe('');
|
|
18
|
+
expect(wrapper.vm.size).toBe('30');
|
|
19
|
+
expect(wrapper.vm.textColor).toBe('var(--Dental-Blue-0)');
|
|
20
|
+
expect(wrapper.vm.iconSize).toBe('20');
|
|
21
|
+
expect(wrapper.vm.readonly).toBe(false);
|
|
22
|
+
expect(wrapper.vm.variant).toBe('flat');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('has data-testid for testing', () => {
|
|
26
|
+
const wrapper = mount(NotificationBubble);
|
|
27
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('applies notification-bubble CSS class', () => {
|
|
31
|
+
const wrapper = mount(NotificationBubble);
|
|
32
|
+
expect(wrapper.find('.notification-bubble').exists()).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Test text display
|
|
37
|
+
describe('Text Display', () => {
|
|
38
|
+
it('displays text when text prop is provided', () => {
|
|
39
|
+
const wrapper = mount(NotificationBubble, {
|
|
40
|
+
props: {
|
|
41
|
+
text: 'Test Notification'
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
expect(wrapper.find('h4').exists()).toBe(true);
|
|
46
|
+
expect(wrapper.find('h4').text()).toBe('Test Notification');
|
|
47
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(false);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('applies text color to text element', () => {
|
|
51
|
+
const wrapper = mount(NotificationBubble, {
|
|
52
|
+
props: {
|
|
53
|
+
text: 'Colored Text',
|
|
54
|
+
textColor: '#FF0000'
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const h4Element = wrapper.find('h4');
|
|
59
|
+
expect(h4Element.exists()).toBe(true);
|
|
60
|
+
// The style would be applied by Vue's style binding
|
|
61
|
+
expect(h4Element.text()).toBe('Colored Text');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('handles empty text', () => {
|
|
65
|
+
const wrapper = mount(NotificationBubble, {
|
|
66
|
+
props: {
|
|
67
|
+
text: ''
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Empty string is falsy for v-if="text", so h4 should not exist
|
|
72
|
+
expect(wrapper.find('h4').exists()).toBe(false);
|
|
73
|
+
// Instead, it should render the icon
|
|
74
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('handles long text', () => {
|
|
78
|
+
const longText = 'This is a very long notification text that might wrap or overflow depending on the container size and styling';
|
|
79
|
+
const wrapper = mount(NotificationBubble, {
|
|
80
|
+
props: {
|
|
81
|
+
text: longText
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
expect(wrapper.find('h4').text()).toBe(longText);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('handles special characters in text', () => {
|
|
89
|
+
const specialText = 'Notification: !@#$%^&*()_+ ñáéíóú ≈≠≤≥';
|
|
90
|
+
const wrapper = mount(NotificationBubble, {
|
|
91
|
+
props: {
|
|
92
|
+
text: specialText
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
expect(wrapper.find('h4').text()).toBe(specialText);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Test icon display
|
|
101
|
+
describe('Icon Display', () => {
|
|
102
|
+
it('displays icon when text prop is not provided', () => {
|
|
103
|
+
const wrapper = mount(NotificationBubble, {
|
|
104
|
+
props: {
|
|
105
|
+
icon: 'mdi-bell'
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
110
|
+
expect(wrapper.find('h4').exists()).toBe(false);
|
|
111
|
+
expect(wrapper.vm.icon).toBe('mdi-bell');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('displays icon when text is undefined', () => {
|
|
115
|
+
const wrapper = mount(NotificationBubble, {
|
|
116
|
+
props: {
|
|
117
|
+
text: undefined,
|
|
118
|
+
icon: 'mdi-notification'
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
123
|
+
expect(wrapper.find('h4').exists()).toBe(false);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('prioritizes text over icon when both are provided', () => {
|
|
127
|
+
const wrapper = mount(NotificationBubble, {
|
|
128
|
+
props: {
|
|
129
|
+
text: 'Text Priority',
|
|
130
|
+
icon: 'mdi-bell'
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
expect(wrapper.find('h4').exists()).toBe(true);
|
|
135
|
+
expect(wrapper.find('h4').text()).toBe('Text Priority');
|
|
136
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(false);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('applies icon size', () => {
|
|
140
|
+
const wrapper = mount(NotificationBubble, {
|
|
141
|
+
props: {
|
|
142
|
+
icon: 'mdi-bell',
|
|
143
|
+
iconSize: '24'
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
expect(wrapper.vm.iconSize).toBe('24');
|
|
148
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('applies icon color', () => {
|
|
152
|
+
const wrapper = mount(NotificationBubble, {
|
|
153
|
+
props: {
|
|
154
|
+
icon: 'mdi-bell',
|
|
155
|
+
textColor: '#00FF00'
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
expect(wrapper.vm.textColor).toBe('#00FF00');
|
|
160
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('handles different icon names', () => {
|
|
164
|
+
const icons = [
|
|
165
|
+
'mdi-bell',
|
|
166
|
+
'heroicons:bell',
|
|
167
|
+
'fa-solid:bell',
|
|
168
|
+
'custom-icon'
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
icons.forEach(iconName => {
|
|
172
|
+
const wrapper = mount(NotificationBubble, {
|
|
173
|
+
props: {
|
|
174
|
+
icon: iconName
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
expect(wrapper.vm.icon).toBe(iconName);
|
|
179
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Test color properties
|
|
185
|
+
describe('Color Properties', () => {
|
|
186
|
+
it('uses default text color', () => {
|
|
187
|
+
const wrapper = mount(NotificationBubble);
|
|
188
|
+
expect(wrapper.vm.textColor).toBe('var(--Dental-Blue-0)');
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('accepts custom text color', () => {
|
|
192
|
+
const wrapper = mount(NotificationBubble, {
|
|
193
|
+
props: {
|
|
194
|
+
textColor: '#FF5722'
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
expect(wrapper.vm.textColor).toBe('#FF5722');
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('uses default empty background color', () => {
|
|
202
|
+
const wrapper = mount(NotificationBubble);
|
|
203
|
+
expect(wrapper.vm.color).toBe('');
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('accepts custom background color', () => {
|
|
207
|
+
const wrapper = mount(NotificationBubble, {
|
|
208
|
+
props: {
|
|
209
|
+
color: '#E3F2FD'
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
expect(wrapper.vm.color).toBe('#E3F2FD');
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('handles CSS color formats', () => {
|
|
217
|
+
const colorFormats = [
|
|
218
|
+
'#FF0000',
|
|
219
|
+
'rgb(255, 0, 0)',
|
|
220
|
+
'rgba(255, 0, 0, 0.5)',
|
|
221
|
+
'hsl(0, 100%, 50%)',
|
|
222
|
+
'red',
|
|
223
|
+
'var(--custom-color)'
|
|
224
|
+
];
|
|
225
|
+
|
|
226
|
+
colorFormats.forEach(color => {
|
|
227
|
+
const wrapper = mount(NotificationBubble, {
|
|
228
|
+
props: {
|
|
229
|
+
color,
|
|
230
|
+
textColor: color
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
expect(wrapper.vm.color).toBe(color);
|
|
235
|
+
expect(wrapper.vm.textColor).toBe(color);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Test size properties
|
|
241
|
+
describe('Size Properties', () => {
|
|
242
|
+
it('uses default size', () => {
|
|
243
|
+
const wrapper = mount(NotificationBubble);
|
|
244
|
+
expect(wrapper.vm.size).toBe('30');
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it('accepts string size', () => {
|
|
248
|
+
const wrapper = mount(NotificationBubble, {
|
|
249
|
+
props: {
|
|
250
|
+
size: '40'
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
expect(wrapper.vm.size).toBe('40');
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('accepts number size', () => {
|
|
258
|
+
const wrapper = mount(NotificationBubble, {
|
|
259
|
+
props: {
|
|
260
|
+
size: 50
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
expect(wrapper.vm.size).toBe(50);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('uses default icon size', () => {
|
|
268
|
+
const wrapper = mount(NotificationBubble);
|
|
269
|
+
expect(wrapper.vm.iconSize).toBe('20');
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('accepts custom icon size', () => {
|
|
273
|
+
const wrapper = mount(NotificationBubble, {
|
|
274
|
+
props: {
|
|
275
|
+
iconSize: '32'
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
expect(wrapper.vm.iconSize).toBe('32');
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('handles different size values', () => {
|
|
283
|
+
const sizes = ['16', '24', '32', '48', '64'];
|
|
284
|
+
|
|
285
|
+
sizes.forEach(size => {
|
|
286
|
+
const wrapper = mount(NotificationBubble, {
|
|
287
|
+
props: {
|
|
288
|
+
size,
|
|
289
|
+
iconSize: size
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
expect(wrapper.vm.size).toBe(size);
|
|
294
|
+
expect(wrapper.vm.iconSize).toBe(size);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// Test state properties
|
|
300
|
+
describe('State Properties', () => {
|
|
301
|
+
it('uses default readonly state', () => {
|
|
302
|
+
const wrapper = mount(NotificationBubble);
|
|
303
|
+
expect(wrapper.vm.readonly).toBe(false);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
it('accepts readonly true', () => {
|
|
307
|
+
const wrapper = mount(NotificationBubble, {
|
|
308
|
+
props: {
|
|
309
|
+
readonly: true
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
expect(wrapper.vm.readonly).toBe(true);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('uses default variant', () => {
|
|
317
|
+
const wrapper = mount(NotificationBubble);
|
|
318
|
+
expect(wrapper.vm.variant).toBe('flat');
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it('accepts custom variant', () => {
|
|
322
|
+
const variants = ['flat', 'outlined', 'contained', 'tonal', 'text'];
|
|
323
|
+
|
|
324
|
+
variants.forEach(variant => {
|
|
325
|
+
const wrapper = mount(NotificationBubble, {
|
|
326
|
+
props: { variant }
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
expect(wrapper.vm.variant).toBe(variant);
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// Test Vuetify integration
|
|
335
|
+
describe('Vuetify Integration', () => {
|
|
336
|
+
it('applies Vuetify button props correctly', () => {
|
|
337
|
+
const wrapper = mount(NotificationBubble, {
|
|
338
|
+
props: {
|
|
339
|
+
color: '#2196F3',
|
|
340
|
+
size: 40,
|
|
341
|
+
variant: 'outlined',
|
|
342
|
+
readonly: true
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
347
|
+
expect(wrapper.vm.color).toBe('#2196F3');
|
|
348
|
+
expect(wrapper.vm.size).toBe(40);
|
|
349
|
+
expect(wrapper.vm.variant).toBe('outlined');
|
|
350
|
+
expect(wrapper.vm.readonly).toBe(true);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it('uses fixed Vuetify props', () => {
|
|
354
|
+
const wrapper = mount(NotificationBubble);
|
|
355
|
+
|
|
356
|
+
// These props are hardcoded in the template
|
|
357
|
+
// elevation="0", flat=true, rounded="xl"
|
|
358
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
// Test accessibility
|
|
363
|
+
describe('Accessibility', () => {
|
|
364
|
+
it('has data-testid for testing', () => {
|
|
365
|
+
const wrapper = mount(NotificationBubble);
|
|
366
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('provides semantic heading for text content', () => {
|
|
370
|
+
const wrapper = mount(NotificationBubble, {
|
|
371
|
+
props: {
|
|
372
|
+
text: 'Important Notification'
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
const heading = wrapper.find('h4');
|
|
377
|
+
expect(heading.exists()).toBe(true);
|
|
378
|
+
expect(heading.text()).toBe('Important Notification');
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
it('uses icon for non-text notifications', () => {
|
|
382
|
+
const wrapper = mount(NotificationBubble, {
|
|
383
|
+
props: {
|
|
384
|
+
icon: 'mdi-alert'
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it('maintains button semantics from v-btn', () => {
|
|
392
|
+
const wrapper = mount(NotificationBubble, {
|
|
393
|
+
props: {
|
|
394
|
+
text: 'Clickable Notification'
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
// v-btn provides button semantics
|
|
399
|
+
expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// Test edge cases
|
|
404
|
+
describe('Edge Cases', () => {
|
|
405
|
+
it('handles undefined text prop', () => {
|
|
406
|
+
const wrapper = mount(NotificationBubble, {
|
|
407
|
+
props: {
|
|
408
|
+
text: undefined,
|
|
409
|
+
icon: 'mdi-bell'
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
expect(wrapper.find('h4').exists()).toBe(false);
|
|
414
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
it('handles null text prop', () => {
|
|
418
|
+
const wrapper = mount(NotificationBubble, {
|
|
419
|
+
props: {
|
|
420
|
+
text: null,
|
|
421
|
+
icon: 'mdi-bell'
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
expect(wrapper.find('h4').exists()).toBe(false);
|
|
426
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it('handles empty string text', () => {
|
|
430
|
+
const wrapper = mount(NotificationBubble, {
|
|
431
|
+
props: {
|
|
432
|
+
text: '',
|
|
433
|
+
icon: 'mdi-bell'
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
// Empty string is falsy for v-if="text", so h4 should not exist
|
|
438
|
+
expect(wrapper.find('h4').exists()).toBe(false);
|
|
439
|
+
// Icon should be rendered instead
|
|
440
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
it('handles missing icon prop when no text', () => {
|
|
444
|
+
const wrapper = mount(NotificationBubble, {
|
|
445
|
+
props: {
|
|
446
|
+
// No text, no icon
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
expect(wrapper.find('h4').exists()).toBe(false);
|
|
451
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
452
|
+
expect(wrapper.vm.icon).toBeUndefined();
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
it('handles zero size values', () => {
|
|
456
|
+
const wrapper = mount(NotificationBubble, {
|
|
457
|
+
props: {
|
|
458
|
+
size: 0,
|
|
459
|
+
iconSize: '0'
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
expect(wrapper.vm.size).toBe(0);
|
|
464
|
+
expect(wrapper.vm.iconSize).toBe('0');
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
it('handles very large size values', () => {
|
|
468
|
+
const wrapper = mount(NotificationBubble, {
|
|
469
|
+
props: {
|
|
470
|
+
size: 1000,
|
|
471
|
+
iconSize: '500'
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
expect(wrapper.vm.size).toBe(1000);
|
|
476
|
+
expect(wrapper.vm.iconSize).toBe('500');
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
it('handles empty string colors', () => {
|
|
480
|
+
const wrapper = mount(NotificationBubble, {
|
|
481
|
+
props: {
|
|
482
|
+
color: '',
|
|
483
|
+
textColor: ''
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
expect(wrapper.vm.color).toBe('');
|
|
488
|
+
expect(wrapper.vm.textColor).toBe('');
|
|
489
|
+
});
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
// Test complex scenarios
|
|
493
|
+
describe('Complex Scenarios', () => {
|
|
494
|
+
it('works with all props configured for text display', () => {
|
|
495
|
+
const wrapper = mount(NotificationBubble, {
|
|
496
|
+
props: {
|
|
497
|
+
text: 'Complete Configuration',
|
|
498
|
+
color: '#E8F5E8',
|
|
499
|
+
textColor: '#2E7D32',
|
|
500
|
+
size: 48,
|
|
501
|
+
variant: 'outlined',
|
|
502
|
+
readonly: true
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
expect(wrapper.vm.text).toBe('Complete Configuration');
|
|
507
|
+
expect(wrapper.vm.color).toBe('#E8F5E8');
|
|
508
|
+
expect(wrapper.vm.textColor).toBe('#2E7D32');
|
|
509
|
+
expect(wrapper.vm.size).toBe(48);
|
|
510
|
+
expect(wrapper.vm.variant).toBe('outlined');
|
|
511
|
+
expect(wrapper.vm.readonly).toBe(true);
|
|
512
|
+
expect(wrapper.find('h4').exists()).toBe(true);
|
|
513
|
+
expect(wrapper.find('h4').text()).toBe('Complete Configuration');
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
it('works with all props configured for icon display', () => {
|
|
517
|
+
const wrapper = mount(NotificationBubble, {
|
|
518
|
+
props: {
|
|
519
|
+
icon: 'mdi-notification-important',
|
|
520
|
+
iconSize: '28',
|
|
521
|
+
color: '#FFEBEE',
|
|
522
|
+
textColor: '#C62828',
|
|
523
|
+
size: 36,
|
|
524
|
+
variant: 'contained',
|
|
525
|
+
readonly: false
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
expect(wrapper.vm.icon).toBe('mdi-notification-important');
|
|
530
|
+
expect(wrapper.vm.iconSize).toBe('28');
|
|
531
|
+
expect(wrapper.vm.color).toBe('#FFEBEE');
|
|
532
|
+
expect(wrapper.vm.textColor).toBe('#C62828');
|
|
533
|
+
expect(wrapper.vm.size).toBe(36);
|
|
534
|
+
expect(wrapper.vm.variant).toBe('contained');
|
|
535
|
+
expect(wrapper.vm.readonly).toBe(false);
|
|
536
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
537
|
+
expect(wrapper.find('h4').exists()).toBe(false);
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
it('handles prop changes dynamically', async () => {
|
|
541
|
+
const wrapper = mount(NotificationBubble, {
|
|
542
|
+
props: {
|
|
543
|
+
text: 'Initial Text',
|
|
544
|
+
color: '#000000'
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
// Initial state
|
|
549
|
+
expect(wrapper.find('h4').exists()).toBe(true);
|
|
550
|
+
expect(wrapper.find('h4').text()).toBe('Initial Text');
|
|
551
|
+
|
|
552
|
+
// Change to icon
|
|
553
|
+
await wrapper.setProps({
|
|
554
|
+
text: undefined,
|
|
555
|
+
icon: 'mdi-bell',
|
|
556
|
+
color: '#FF0000'
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
expect(wrapper.find('h4').exists()).toBe(false);
|
|
560
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(true);
|
|
561
|
+
expect(wrapper.vm.color).toBe('#FF0000');
|
|
562
|
+
|
|
563
|
+
// Change back to text
|
|
564
|
+
await wrapper.setProps({
|
|
565
|
+
text: 'Updated Text',
|
|
566
|
+
color: '#00FF00'
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
expect(wrapper.find('h4').exists()).toBe(true);
|
|
570
|
+
expect(wrapper.find('h4').text()).toBe('Updated Text');
|
|
571
|
+
expect(wrapper.find('[data-testid="v-icon"]').exists()).toBe(false);
|
|
572
|
+
expect(wrapper.vm.color).toBe('#00FF00');
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
it('maintains consistent styling across different content types', () => {
|
|
576
|
+
const commonProps = {
|
|
577
|
+
color: '#F3E5F5',
|
|
578
|
+
textColor: '#7B1FA2',
|
|
579
|
+
size: 32,
|
|
580
|
+
variant: 'tonal'
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
// Text version
|
|
584
|
+
const textWrapper = mount(NotificationBubble, {
|
|
585
|
+
props: {
|
|
586
|
+
...commonProps,
|
|
587
|
+
text: '5'
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
// Icon version
|
|
592
|
+
const iconWrapper = mount(NotificationBubble, {
|
|
593
|
+
props: {
|
|
594
|
+
...commonProps,
|
|
595
|
+
icon: 'mdi-numeric-5',
|
|
596
|
+
iconSize: '24'
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
// Both should have consistent styling
|
|
601
|
+
expect(textWrapper.vm.color).toBe(iconWrapper.vm.color);
|
|
602
|
+
expect(textWrapper.vm.textColor).toBe(iconWrapper.vm.textColor);
|
|
603
|
+
expect(textWrapper.vm.size).toBe(iconWrapper.vm.size);
|
|
604
|
+
expect(textWrapper.vm.variant).toBe(iconWrapper.vm.variant);
|
|
605
|
+
});
|
|
606
|
+
});
|
|
607
607
|
});
|