@zap-wunschlachen/wl-shared-components 1.0.25 → 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 -315
- 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,252 +1,252 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { mount } from '@vue/test-utils';
|
|
3
|
-
import FavIcon from '@components/Icons/FavIcon.vue';
|
|
4
|
-
|
|
5
|
-
describe('FavIcon Icon', () => {
|
|
6
|
-
describe('Rendering', () => {
|
|
7
|
-
it('renders as SVG element', () => {
|
|
8
|
-
const wrapper = mount(FavIcon);
|
|
9
|
-
expect(wrapper.find('svg').exists()).toBe(true);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('has correct SVG attributes', () => {
|
|
13
|
-
const wrapper = mount(FavIcon);
|
|
14
|
-
const svg = wrapper.find('svg');
|
|
15
|
-
|
|
16
|
-
expect(svg.attributes('width')).toBe('30');
|
|
17
|
-
expect(svg.attributes('height')).toBe('30');
|
|
18
|
-
expect(svg.attributes('viewBox')).toBe('0 0 30 30');
|
|
19
|
-
expect(svg.attributes('fill')).toBe('none');
|
|
20
|
-
expect(svg.attributes('xmlns')).toBe('http://www.w3.org/2000/svg');
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('contains exactly 3 path elements', () => {
|
|
24
|
-
const wrapper = mount(FavIcon);
|
|
25
|
-
const paths = wrapper.findAll('path');
|
|
26
|
-
expect(paths).toHaveLength(3);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe('Path Structure', () => {
|
|
31
|
-
it('paths represent favicon shape', () => {
|
|
32
|
-
const wrapper = mount(FavIcon);
|
|
33
|
-
const paths = wrapper.findAll('path');
|
|
34
|
-
|
|
35
|
-
const firstPathData = paths[0].attributes('d');
|
|
36
|
-
expect(firstPathData).toContain('M15 30C23.271');
|
|
37
|
-
expect(firstPathData).toContain('C6.72904 0 0 6.72904');
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('paths have correct fill properties', () => {
|
|
41
|
-
const wrapper = mount(FavIcon);
|
|
42
|
-
const paths = wrapper.findAll('path');
|
|
43
|
-
|
|
44
|
-
paths.forEach(path => {
|
|
45
|
-
expect(path.attributes('fill')).toBe('#172774');
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('paths form complete favicon shape', () => {
|
|
50
|
-
const wrapper = mount(FavIcon);
|
|
51
|
-
const paths = wrapper.findAll('path');
|
|
52
|
-
|
|
53
|
-
paths.forEach(path => {
|
|
54
|
-
const pathData = path.attributes('d');
|
|
55
|
-
expect(pathData).toBeTruthy();
|
|
56
|
-
expect(pathData.length).toBeGreaterThan(10);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('Visual Properties', () => {
|
|
62
|
-
it('uses correct brand color for fill', () => {
|
|
63
|
-
const wrapper = mount(FavIcon);
|
|
64
|
-
const paths = wrapper.findAll('path');
|
|
65
|
-
|
|
66
|
-
paths.forEach(path => {
|
|
67
|
-
expect(path.attributes('fill')).toBe('#172774');
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('svg container has no fill initially', () => {
|
|
72
|
-
const wrapper = mount(FavIcon);
|
|
73
|
-
const svg = wrapper.find('svg');
|
|
74
|
-
|
|
75
|
-
expect(svg.attributes('fill')).toBe('none');
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
describe('Favicon Dimensions', () => {
|
|
80
|
-
it('uses standard favicon size', () => {
|
|
81
|
-
const wrapper = mount(FavIcon);
|
|
82
|
-
const svg = wrapper.find('svg');
|
|
83
|
-
|
|
84
|
-
expect(svg.attributes('width')).toBe('30');
|
|
85
|
-
expect(svg.attributes('height')).toBe('30');
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it('maintains square aspect ratio', () => {
|
|
89
|
-
const wrapper = mount(FavIcon);
|
|
90
|
-
const svg = wrapper.find('svg');
|
|
91
|
-
|
|
92
|
-
const width = svg.attributes('width');
|
|
93
|
-
const height = svg.attributes('height');
|
|
94
|
-
expect(width).toBe(height);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('has correct viewBox for 100x100 canvas', () => {
|
|
98
|
-
const wrapper = mount(FavIcon);
|
|
99
|
-
const svg = wrapper.find('svg');
|
|
100
|
-
|
|
101
|
-
expect(svg.attributes('viewBox')).toBe('0 0 30 30');
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
describe('Path Geometry', () => {
|
|
106
|
-
it('first path starts from correct coordinates', () => {
|
|
107
|
-
const wrapper = mount(FavIcon);
|
|
108
|
-
const paths = wrapper.findAll('path');
|
|
109
|
-
|
|
110
|
-
const firstPathData = paths[0].attributes('d');
|
|
111
|
-
expect(firstPathData).toMatch(/^M15\s+30C/);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('contains multiple coordinate points across paths', () => {
|
|
115
|
-
const wrapper = mount(FavIcon);
|
|
116
|
-
const paths = wrapper.findAll('path');
|
|
117
|
-
|
|
118
|
-
let totalCoordinateMatches = 0;
|
|
119
|
-
paths.forEach(path => {
|
|
120
|
-
const pathData = path.attributes('d');
|
|
121
|
-
const coordinateMatches = pathData.match(/\d+\.?\d*\s+\d+\.?\d*/g) || [];
|
|
122
|
-
totalCoordinateMatches += coordinateMatches.length;
|
|
123
|
-
});
|
|
124
|
-
expect(totalCoordinateMatches).toBeGreaterThan(10);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('uses proper path commands', () => {
|
|
128
|
-
const wrapper = mount(FavIcon);
|
|
129
|
-
const paths = wrapper.findAll('path');
|
|
130
|
-
|
|
131
|
-
paths.forEach(path => {
|
|
132
|
-
const pathData = path.attributes('d');
|
|
133
|
-
// Should contain path commands like M, L, C, Z
|
|
134
|
-
expect(pathData).toMatch(/[MLCZ]/);
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
describe('Component Structure', () => {
|
|
140
|
-
it('is suitable for favicon usage', () => {
|
|
141
|
-
const wrapper = mount(FavIcon);
|
|
142
|
-
const svg = wrapper.find('svg');
|
|
143
|
-
|
|
144
|
-
// Should be square and reasonably sized
|
|
145
|
-
expect(svg.attributes('width')).toBe('30');
|
|
146
|
-
expect(svg.attributes('height')).toBe('30');
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('has solid fill suitable for small sizes', () => {
|
|
150
|
-
const wrapper = mount(FavIcon);
|
|
151
|
-
const paths = wrapper.findAll('path');
|
|
152
|
-
|
|
153
|
-
// Should have solid fill rather than just stroke for visibility at small sizes
|
|
154
|
-
paths.forEach(path => {
|
|
155
|
-
expect(path.attributes('fill')).toBe('#172774');
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
describe('Accessibility', () => {
|
|
161
|
-
it('svg is properly structured for screen readers', () => {
|
|
162
|
-
const wrapper = mount(FavIcon);
|
|
163
|
-
const svg = wrapper.find('svg');
|
|
164
|
-
|
|
165
|
-
expect(svg.element.tagName.toLowerCase()).toBe('svg');
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
describe('Component Integration', () => {
|
|
170
|
-
it('can be mounted without props', () => {
|
|
171
|
-
expect(() => {
|
|
172
|
-
mount(FavIcon);
|
|
173
|
-
}).not.toThrow();
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('renders consistently on multiple mounts', () => {
|
|
177
|
-
const wrapper1 = mount(FavIcon);
|
|
178
|
-
const wrapper2 = mount(FavIcon);
|
|
179
|
-
|
|
180
|
-
expect(wrapper1.html()).toBe(wrapper2.html());
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it('maintains favicon integrity', () => {
|
|
184
|
-
const wrapper = mount(FavIcon);
|
|
185
|
-
const paths = wrapper.findAll('path');
|
|
186
|
-
|
|
187
|
-
expect(paths.length).toBe(3);
|
|
188
|
-
paths.forEach(path => {
|
|
189
|
-
expect(path.exists()).toBe(true);
|
|
190
|
-
expect(path.attributes('d')).toBeTruthy();
|
|
191
|
-
expect(path.attributes('fill')).toBeTruthy();
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it('suitable for use as application favicon', () => {
|
|
196
|
-
const wrapper = mount(FavIcon);
|
|
197
|
-
const svg = wrapper.find('svg');
|
|
198
|
-
|
|
199
|
-
// Standard favicon requirements
|
|
200
|
-
expect(svg.attributes('width')).toBe('30');
|
|
201
|
-
expect(svg.attributes('height')).toBe('30');
|
|
202
|
-
expect(wrapper.findAll('path')[0].attributes('fill')).toBe('#172774');
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
describe('Brand Identity', () => {
|
|
207
|
-
it('uses brand color consistently', () => {
|
|
208
|
-
const wrapper = mount(FavIcon);
|
|
209
|
-
const paths = wrapper.findAll('path');
|
|
210
|
-
|
|
211
|
-
const brandColor = '#172774';
|
|
212
|
-
paths.forEach(path => {
|
|
213
|
-
expect(path.attributes('fill')).toBe(brandColor);
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
it('represents identifiable brand mark', () => {
|
|
218
|
-
const wrapper = mount(FavIcon);
|
|
219
|
-
const paths = wrapper.findAll('path');
|
|
220
|
-
|
|
221
|
-
// Should have substantial path data for brand recognition
|
|
222
|
-
paths.forEach(path => {
|
|
223
|
-
const pathData = path.attributes('d');
|
|
224
|
-
expect(pathData).toBeTruthy();
|
|
225
|
-
expect(typeof pathData).toBe('string');
|
|
226
|
-
expect(pathData.length).toBeGreaterThan(20);
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
describe('Icon Semantics', () => {
|
|
232
|
-
it('designed for small size visibility', () => {
|
|
233
|
-
const wrapper = mount(FavIcon);
|
|
234
|
-
const paths = wrapper.findAll('path');
|
|
235
|
-
|
|
236
|
-
// Should use fill rather than complex strokes for small size clarity
|
|
237
|
-
paths.forEach(path => {
|
|
238
|
-
expect(path.attributes('fill')).toBeTruthy();
|
|
239
|
-
});
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it('maintains visual clarity at favicon size', () => {
|
|
243
|
-
const wrapper = mount(FavIcon);
|
|
244
|
-
const svg = wrapper.find('svg');
|
|
245
|
-
|
|
246
|
-
// 100x100 is appropriate base size for favicon scaling
|
|
247
|
-
expect(svg.attributes('viewBox')).toBe('0 0 30 30');
|
|
248
|
-
expect(svg.attributes('width')).toBe('30');
|
|
249
|
-
expect(svg.attributes('height')).toBe('30');
|
|
250
|
-
});
|
|
251
|
-
});
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import FavIcon from '@components/Icons/FavIcon.vue';
|
|
4
|
+
|
|
5
|
+
describe('FavIcon Icon', () => {
|
|
6
|
+
describe('Rendering', () => {
|
|
7
|
+
it('renders as SVG element', () => {
|
|
8
|
+
const wrapper = mount(FavIcon);
|
|
9
|
+
expect(wrapper.find('svg').exists()).toBe(true);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('has correct SVG attributes', () => {
|
|
13
|
+
const wrapper = mount(FavIcon);
|
|
14
|
+
const svg = wrapper.find('svg');
|
|
15
|
+
|
|
16
|
+
expect(svg.attributes('width')).toBe('30');
|
|
17
|
+
expect(svg.attributes('height')).toBe('30');
|
|
18
|
+
expect(svg.attributes('viewBox')).toBe('0 0 30 30');
|
|
19
|
+
expect(svg.attributes('fill')).toBe('none');
|
|
20
|
+
expect(svg.attributes('xmlns')).toBe('http://www.w3.org/2000/svg');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('contains exactly 3 path elements', () => {
|
|
24
|
+
const wrapper = mount(FavIcon);
|
|
25
|
+
const paths = wrapper.findAll('path');
|
|
26
|
+
expect(paths).toHaveLength(3);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe('Path Structure', () => {
|
|
31
|
+
it('paths represent favicon shape', () => {
|
|
32
|
+
const wrapper = mount(FavIcon);
|
|
33
|
+
const paths = wrapper.findAll('path');
|
|
34
|
+
|
|
35
|
+
const firstPathData = paths[0].attributes('d');
|
|
36
|
+
expect(firstPathData).toContain('M15 30C23.271');
|
|
37
|
+
expect(firstPathData).toContain('C6.72904 0 0 6.72904');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('paths have correct fill properties', () => {
|
|
41
|
+
const wrapper = mount(FavIcon);
|
|
42
|
+
const paths = wrapper.findAll('path');
|
|
43
|
+
|
|
44
|
+
paths.forEach(path => {
|
|
45
|
+
expect(path.attributes('fill')).toBe('#172774');
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('paths form complete favicon shape', () => {
|
|
50
|
+
const wrapper = mount(FavIcon);
|
|
51
|
+
const paths = wrapper.findAll('path');
|
|
52
|
+
|
|
53
|
+
paths.forEach(path => {
|
|
54
|
+
const pathData = path.attributes('d');
|
|
55
|
+
expect(pathData).toBeTruthy();
|
|
56
|
+
expect(pathData.length).toBeGreaterThan(10);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('Visual Properties', () => {
|
|
62
|
+
it('uses correct brand color for fill', () => {
|
|
63
|
+
const wrapper = mount(FavIcon);
|
|
64
|
+
const paths = wrapper.findAll('path');
|
|
65
|
+
|
|
66
|
+
paths.forEach(path => {
|
|
67
|
+
expect(path.attributes('fill')).toBe('#172774');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('svg container has no fill initially', () => {
|
|
72
|
+
const wrapper = mount(FavIcon);
|
|
73
|
+
const svg = wrapper.find('svg');
|
|
74
|
+
|
|
75
|
+
expect(svg.attributes('fill')).toBe('none');
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe('Favicon Dimensions', () => {
|
|
80
|
+
it('uses standard favicon size', () => {
|
|
81
|
+
const wrapper = mount(FavIcon);
|
|
82
|
+
const svg = wrapper.find('svg');
|
|
83
|
+
|
|
84
|
+
expect(svg.attributes('width')).toBe('30');
|
|
85
|
+
expect(svg.attributes('height')).toBe('30');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('maintains square aspect ratio', () => {
|
|
89
|
+
const wrapper = mount(FavIcon);
|
|
90
|
+
const svg = wrapper.find('svg');
|
|
91
|
+
|
|
92
|
+
const width = svg.attributes('width');
|
|
93
|
+
const height = svg.attributes('height');
|
|
94
|
+
expect(width).toBe(height);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('has correct viewBox for 100x100 canvas', () => {
|
|
98
|
+
const wrapper = mount(FavIcon);
|
|
99
|
+
const svg = wrapper.find('svg');
|
|
100
|
+
|
|
101
|
+
expect(svg.attributes('viewBox')).toBe('0 0 30 30');
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe('Path Geometry', () => {
|
|
106
|
+
it('first path starts from correct coordinates', () => {
|
|
107
|
+
const wrapper = mount(FavIcon);
|
|
108
|
+
const paths = wrapper.findAll('path');
|
|
109
|
+
|
|
110
|
+
const firstPathData = paths[0].attributes('d');
|
|
111
|
+
expect(firstPathData).toMatch(/^M15\s+30C/);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('contains multiple coordinate points across paths', () => {
|
|
115
|
+
const wrapper = mount(FavIcon);
|
|
116
|
+
const paths = wrapper.findAll('path');
|
|
117
|
+
|
|
118
|
+
let totalCoordinateMatches = 0;
|
|
119
|
+
paths.forEach(path => {
|
|
120
|
+
const pathData = path.attributes('d');
|
|
121
|
+
const coordinateMatches = pathData.match(/\d+\.?\d*\s+\d+\.?\d*/g) || [];
|
|
122
|
+
totalCoordinateMatches += coordinateMatches.length;
|
|
123
|
+
});
|
|
124
|
+
expect(totalCoordinateMatches).toBeGreaterThan(10);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('uses proper path commands', () => {
|
|
128
|
+
const wrapper = mount(FavIcon);
|
|
129
|
+
const paths = wrapper.findAll('path');
|
|
130
|
+
|
|
131
|
+
paths.forEach(path => {
|
|
132
|
+
const pathData = path.attributes('d');
|
|
133
|
+
// Should contain path commands like M, L, C, Z
|
|
134
|
+
expect(pathData).toMatch(/[MLCZ]/);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe('Component Structure', () => {
|
|
140
|
+
it('is suitable for favicon usage', () => {
|
|
141
|
+
const wrapper = mount(FavIcon);
|
|
142
|
+
const svg = wrapper.find('svg');
|
|
143
|
+
|
|
144
|
+
// Should be square and reasonably sized
|
|
145
|
+
expect(svg.attributes('width')).toBe('30');
|
|
146
|
+
expect(svg.attributes('height')).toBe('30');
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('has solid fill suitable for small sizes', () => {
|
|
150
|
+
const wrapper = mount(FavIcon);
|
|
151
|
+
const paths = wrapper.findAll('path');
|
|
152
|
+
|
|
153
|
+
// Should have solid fill rather than just stroke for visibility at small sizes
|
|
154
|
+
paths.forEach(path => {
|
|
155
|
+
expect(path.attributes('fill')).toBe('#172774');
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe('Accessibility', () => {
|
|
161
|
+
it('svg is properly structured for screen readers', () => {
|
|
162
|
+
const wrapper = mount(FavIcon);
|
|
163
|
+
const svg = wrapper.find('svg');
|
|
164
|
+
|
|
165
|
+
expect(svg.element.tagName.toLowerCase()).toBe('svg');
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
describe('Component Integration', () => {
|
|
170
|
+
it('can be mounted without props', () => {
|
|
171
|
+
expect(() => {
|
|
172
|
+
mount(FavIcon);
|
|
173
|
+
}).not.toThrow();
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('renders consistently on multiple mounts', () => {
|
|
177
|
+
const wrapper1 = mount(FavIcon);
|
|
178
|
+
const wrapper2 = mount(FavIcon);
|
|
179
|
+
|
|
180
|
+
expect(wrapper1.html()).toBe(wrapper2.html());
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('maintains favicon integrity', () => {
|
|
184
|
+
const wrapper = mount(FavIcon);
|
|
185
|
+
const paths = wrapper.findAll('path');
|
|
186
|
+
|
|
187
|
+
expect(paths.length).toBe(3);
|
|
188
|
+
paths.forEach(path => {
|
|
189
|
+
expect(path.exists()).toBe(true);
|
|
190
|
+
expect(path.attributes('d')).toBeTruthy();
|
|
191
|
+
expect(path.attributes('fill')).toBeTruthy();
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('suitable for use as application favicon', () => {
|
|
196
|
+
const wrapper = mount(FavIcon);
|
|
197
|
+
const svg = wrapper.find('svg');
|
|
198
|
+
|
|
199
|
+
// Standard favicon requirements
|
|
200
|
+
expect(svg.attributes('width')).toBe('30');
|
|
201
|
+
expect(svg.attributes('height')).toBe('30');
|
|
202
|
+
expect(wrapper.findAll('path')[0].attributes('fill')).toBe('#172774');
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
describe('Brand Identity', () => {
|
|
207
|
+
it('uses brand color consistently', () => {
|
|
208
|
+
const wrapper = mount(FavIcon);
|
|
209
|
+
const paths = wrapper.findAll('path');
|
|
210
|
+
|
|
211
|
+
const brandColor = '#172774';
|
|
212
|
+
paths.forEach(path => {
|
|
213
|
+
expect(path.attributes('fill')).toBe(brandColor);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('represents identifiable brand mark', () => {
|
|
218
|
+
const wrapper = mount(FavIcon);
|
|
219
|
+
const paths = wrapper.findAll('path');
|
|
220
|
+
|
|
221
|
+
// Should have substantial path data for brand recognition
|
|
222
|
+
paths.forEach(path => {
|
|
223
|
+
const pathData = path.attributes('d');
|
|
224
|
+
expect(pathData).toBeTruthy();
|
|
225
|
+
expect(typeof pathData).toBe('string');
|
|
226
|
+
expect(pathData.length).toBeGreaterThan(20);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
describe('Icon Semantics', () => {
|
|
232
|
+
it('designed for small size visibility', () => {
|
|
233
|
+
const wrapper = mount(FavIcon);
|
|
234
|
+
const paths = wrapper.findAll('path');
|
|
235
|
+
|
|
236
|
+
// Should use fill rather than complex strokes for small size clarity
|
|
237
|
+
paths.forEach(path => {
|
|
238
|
+
expect(path.attributes('fill')).toBeTruthy();
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('maintains visual clarity at favicon size', () => {
|
|
243
|
+
const wrapper = mount(FavIcon);
|
|
244
|
+
const svg = wrapper.find('svg');
|
|
245
|
+
|
|
246
|
+
// 100x100 is appropriate base size for favicon scaling
|
|
247
|
+
expect(svg.attributes('viewBox')).toBe('0 0 30 30');
|
|
248
|
+
expect(svg.attributes('width')).toBe('30');
|
|
249
|
+
expect(svg.attributes('height')).toBe('30');
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
252
|
});
|