@zap-wunschlachen/wl-shared-components 1.0.12 → 1.0.14
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 +149 -147
- 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 +96 -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 +28 -28
- package/src/components/Appointment/Card/Actions.vue +72 -72
- package/src/components/Appointment/Card/Card.css +80 -80
- package/src/components/Appointment/Card/Card.vue +87 -81
- 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/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/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/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 -0
- package/src/components/Loader/Loader.vue +65 -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 +304 -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 +22 -22
- package/src/constants/iconEnums.ts +3 -3
- package/src/i18n/i18n.ts +15 -15
- package/src/i18n/locales/de.json +27 -27
- package/src/i18n/locales/en.json +27 -27
- package/src/index.ts +31 -31
- package/src/main.ts +11 -11
- package/src/plugins/vuetify.ts +131 -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 +101 -42
- 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,275 +1,275 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { mount } from '@vue/test-utils';
|
|
3
|
-
import FilledCircle from '@components/Icons/FilledCircle.vue';
|
|
4
|
-
|
|
5
|
-
describe('FilledCircle Icon', () => {
|
|
6
|
-
describe('Rendering', () => {
|
|
7
|
-
it('renders as SVG element', () => {
|
|
8
|
-
const wrapper = mount(FilledCircle);
|
|
9
|
-
expect(wrapper.find('svg').exists()).toBe(true);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('has correct SVG attributes', () => {
|
|
13
|
-
const wrapper = mount(FilledCircle);
|
|
14
|
-
const svg = wrapper.find('svg');
|
|
15
|
-
|
|
16
|
-
expect(svg.attributes('width')).toBe('16');
|
|
17
|
-
expect(svg.attributes('height')).toBe('16');
|
|
18
|
-
expect(svg.attributes('viewBox')).toBe('0 0 16 16');
|
|
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 1 circle element', () => {
|
|
24
|
-
const wrapper = mount(FilledCircle);
|
|
25
|
-
const circles = wrapper.findAll('circle');
|
|
26
|
-
expect(circles).toHaveLength(1);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe('Circle Properties', () => {
|
|
31
|
-
it('circle is centered in viewBox', () => {
|
|
32
|
-
const wrapper = mount(FilledCircle);
|
|
33
|
-
const circle = wrapper.find('circle');
|
|
34
|
-
|
|
35
|
-
expect(circle.attributes('cx')).toBe('8');
|
|
36
|
-
expect(circle.attributes('cy')).toBe('8');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('circle fills entire viewBox', () => {
|
|
40
|
-
const wrapper = mount(FilledCircle);
|
|
41
|
-
const circle = wrapper.find('circle');
|
|
42
|
-
|
|
43
|
-
expect(circle.attributes('r')).toBe('8');
|
|
44
|
-
// With radius 8 and center at (8,8), circle spans 0-16 in both dimensions
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('circle has correct fill color', () => {
|
|
48
|
-
const wrapper = mount(FilledCircle);
|
|
49
|
-
const circle = wrapper.find('circle');
|
|
50
|
-
|
|
51
|
-
expect(circle.attributes('fill')).toBe('#C1C1C2');
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('circle has no stroke', () => {
|
|
55
|
-
const wrapper = mount(FilledCircle);
|
|
56
|
-
const circle = wrapper.find('circle');
|
|
57
|
-
|
|
58
|
-
expect(circle.attributes('stroke')).toBeUndefined();
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
describe('Visual Properties', () => {
|
|
63
|
-
it('uses gray fill color', () => {
|
|
64
|
-
const wrapper = mount(FilledCircle);
|
|
65
|
-
const circle = wrapper.find('circle');
|
|
66
|
-
|
|
67
|
-
expect(circle.attributes('fill')).toBe('#C1C1C2');
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('svg container has no default fill', () => {
|
|
71
|
-
const wrapper = mount(FilledCircle);
|
|
72
|
-
const svg = wrapper.find('svg');
|
|
73
|
-
|
|
74
|
-
expect(svg.attributes('fill')).toBe('none');
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('creates solid filled appearance', () => {
|
|
78
|
-
const wrapper = mount(FilledCircle);
|
|
79
|
-
const circle = wrapper.find('circle');
|
|
80
|
-
|
|
81
|
-
// Should have fill but no stroke for solid appearance
|
|
82
|
-
expect(circle.attributes('fill')).toBeTruthy();
|
|
83
|
-
expect(circle.attributes('stroke')).toBeUndefined();
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
describe('Dimensions', () => {
|
|
88
|
-
it('uses compact 16x16 size', () => {
|
|
89
|
-
const wrapper = mount(FilledCircle);
|
|
90
|
-
const svg = wrapper.find('svg');
|
|
91
|
-
|
|
92
|
-
expect(svg.attributes('width')).toBe('16');
|
|
93
|
-
expect(svg.attributes('height')).toBe('16');
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('maintains square aspect ratio', () => {
|
|
97
|
-
const wrapper = mount(FilledCircle);
|
|
98
|
-
const svg = wrapper.find('svg');
|
|
99
|
-
|
|
100
|
-
const width = svg.attributes('width');
|
|
101
|
-
const height = svg.attributes('height');
|
|
102
|
-
expect(width).toBe(height);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('has matching viewBox dimensions', () => {
|
|
106
|
-
const wrapper = mount(FilledCircle);
|
|
107
|
-
const svg = wrapper.find('svg');
|
|
108
|
-
|
|
109
|
-
expect(svg.attributes('viewBox')).toBe('0 0 16 16');
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
describe('Circle Geometry', () => {
|
|
114
|
-
it('circle is perfectly centered', () => {
|
|
115
|
-
const wrapper = mount(FilledCircle);
|
|
116
|
-
const circle = wrapper.find('circle');
|
|
117
|
-
|
|
118
|
-
const cx = parseInt(circle.attributes('cx'));
|
|
119
|
-
const cy = parseInt(circle.attributes('cy'));
|
|
120
|
-
const r = parseInt(circle.attributes('r'));
|
|
121
|
-
|
|
122
|
-
// Center should be at half the viewBox dimensions
|
|
123
|
-
expect(cx).toBe(8);
|
|
124
|
-
expect(cy).toBe(8);
|
|
125
|
-
expect(r).toBe(8);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it('circle touches all edges of viewBox', () => {
|
|
129
|
-
const wrapper = mount(FilledCircle);
|
|
130
|
-
const circle = wrapper.find('circle');
|
|
131
|
-
|
|
132
|
-
const cx = parseInt(circle.attributes('cx'));
|
|
133
|
-
const cy = parseInt(circle.attributes('cy'));
|
|
134
|
-
const r = parseInt(circle.attributes('r'));
|
|
135
|
-
|
|
136
|
-
// Circle should extend from 0 to 16 in both dimensions
|
|
137
|
-
expect(cx - r).toBe(0); // Left edge
|
|
138
|
-
expect(cx + r).toBe(16); // Right edge
|
|
139
|
-
expect(cy - r).toBe(0); // Top edge
|
|
140
|
-
expect(cy + r).toBe(16); // Bottom edge
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('forms perfect circle', () => {
|
|
144
|
-
const wrapper = mount(FilledCircle);
|
|
145
|
-
const circle = wrapper.find('circle');
|
|
146
|
-
|
|
147
|
-
// All radii should be equal
|
|
148
|
-
const r = circle.attributes('r');
|
|
149
|
-
expect(r).toBe('8');
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
describe('Component Structure', () => {
|
|
154
|
-
it('suitable for UI indicators', () => {
|
|
155
|
-
const wrapper = mount(FilledCircle);
|
|
156
|
-
const svg = wrapper.find('svg');
|
|
157
|
-
|
|
158
|
-
// Small size appropriate for bullets, status indicators, etc.
|
|
159
|
-
expect(svg.attributes('width')).toBe('16');
|
|
160
|
-
expect(svg.attributes('height')).toBe('16');
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('uses neutral gray color', () => {
|
|
164
|
-
const wrapper = mount(FilledCircle);
|
|
165
|
-
const circle = wrapper.find('circle');
|
|
166
|
-
|
|
167
|
-
// Gray color suggests neutral/inactive state
|
|
168
|
-
expect(circle.attributes('fill')).toBe('#C1C1C2');
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
describe('Accessibility', () => {
|
|
173
|
-
it('svg is properly structured for screen readers', () => {
|
|
174
|
-
const wrapper = mount(FilledCircle);
|
|
175
|
-
const svg = wrapper.find('svg');
|
|
176
|
-
|
|
177
|
-
expect(svg.element.tagName.toLowerCase()).toBe('svg');
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('simple structure for clear recognition', () => {
|
|
181
|
-
const wrapper = mount(FilledCircle);
|
|
182
|
-
|
|
183
|
-
// Should have minimal, clear structure
|
|
184
|
-
expect(wrapper.findAll('circle')).toHaveLength(1);
|
|
185
|
-
expect(wrapper.findAll('path')).toHaveLength(0);
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
describe('Component Integration', () => {
|
|
190
|
-
it('can be mounted without props', () => {
|
|
191
|
-
expect(() => {
|
|
192
|
-
mount(FilledCircle);
|
|
193
|
-
}).not.toThrow();
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it('renders consistently on multiple mounts', () => {
|
|
197
|
-
const wrapper1 = mount(FilledCircle);
|
|
198
|
-
const wrapper2 = mount(FilledCircle);
|
|
199
|
-
|
|
200
|
-
expect(wrapper1.html()).toBe(wrapper2.html());
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('maintains circle integrity', () => {
|
|
204
|
-
const wrapper = mount(FilledCircle);
|
|
205
|
-
const circle = wrapper.find('circle');
|
|
206
|
-
|
|
207
|
-
expect(circle.exists()).toBe(true);
|
|
208
|
-
expect(circle.attributes('cx')).toBeTruthy();
|
|
209
|
-
expect(circle.attributes('cy')).toBeTruthy();
|
|
210
|
-
expect(circle.attributes('r')).toBeTruthy();
|
|
211
|
-
expect(circle.attributes('fill')).toBeTruthy();
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it('suitable for various UI contexts', () => {
|
|
215
|
-
const wrapper = mount(FilledCircle);
|
|
216
|
-
|
|
217
|
-
// Small, neutral, and simple - good for:
|
|
218
|
-
// - List bullets
|
|
219
|
-
// - Status indicators
|
|
220
|
-
// - Form elements
|
|
221
|
-
// - Navigation dots
|
|
222
|
-
expect(wrapper.find('svg').attributes('width')).toBe('16');
|
|
223
|
-
expect(wrapper.find('circle').attributes('fill')).toBe('#C1C1C2');
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
describe('Icon Semantics', () => {
|
|
228
|
-
it('represents filled state or bullet point', () => {
|
|
229
|
-
const wrapper = mount(FilledCircle);
|
|
230
|
-
const circle = wrapper.find('circle');
|
|
231
|
-
|
|
232
|
-
// Solid fill suggests "filled" or "active" state
|
|
233
|
-
expect(circle.attributes('fill')).toBe('#C1C1C2');
|
|
234
|
-
expect(circle.attributes('stroke')).toBeUndefined();
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
it('uses appropriate size for inline usage', () => {
|
|
238
|
-
const wrapper = mount(FilledCircle);
|
|
239
|
-
const svg = wrapper.find('svg');
|
|
240
|
-
|
|
241
|
-
// 16px is good size for inline with text or as small indicator
|
|
242
|
-
expect(svg.attributes('width')).toBe('16');
|
|
243
|
-
expect(svg.attributes('height')).toBe('16');
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
it('neutral color suggests inactive or default state', () => {
|
|
247
|
-
const wrapper = mount(FilledCircle);
|
|
248
|
-
const circle = wrapper.find('circle');
|
|
249
|
-
|
|
250
|
-
// Gray color typically indicates neutral/inactive state
|
|
251
|
-
const fillColor = circle.attributes('fill');
|
|
252
|
-
expect(fillColor).toBe('#C1C1C2');
|
|
253
|
-
expect(fillColor.toLowerCase()).toMatch(/^#[c-f]/); // Grayish color range
|
|
254
|
-
});
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
describe('Visual Design', () => {
|
|
258
|
-
it('provides clear visual weight', () => {
|
|
259
|
-
const wrapper = mount(FilledCircle);
|
|
260
|
-
const circle = wrapper.find('circle');
|
|
261
|
-
|
|
262
|
-
// Solid fill provides clear visual presence
|
|
263
|
-
expect(circle.attributes('fill')).toBeTruthy();
|
|
264
|
-
expect(circle.attributes('fill')).not.toBe('none');
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it('maintains simplicity for scalability', () => {
|
|
268
|
-
const wrapper = mount(FilledCircle);
|
|
269
|
-
|
|
270
|
-
// Simple single-element design scales well
|
|
271
|
-
expect(wrapper.findAll('*')).toHaveLength(2); // svg + circle
|
|
272
|
-
expect(wrapper.find('circle').exists()).toBe(true);
|
|
273
|
-
});
|
|
274
|
-
});
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import FilledCircle from '@components/Icons/FilledCircle.vue';
|
|
4
|
+
|
|
5
|
+
describe('FilledCircle Icon', () => {
|
|
6
|
+
describe('Rendering', () => {
|
|
7
|
+
it('renders as SVG element', () => {
|
|
8
|
+
const wrapper = mount(FilledCircle);
|
|
9
|
+
expect(wrapper.find('svg').exists()).toBe(true);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('has correct SVG attributes', () => {
|
|
13
|
+
const wrapper = mount(FilledCircle);
|
|
14
|
+
const svg = wrapper.find('svg');
|
|
15
|
+
|
|
16
|
+
expect(svg.attributes('width')).toBe('16');
|
|
17
|
+
expect(svg.attributes('height')).toBe('16');
|
|
18
|
+
expect(svg.attributes('viewBox')).toBe('0 0 16 16');
|
|
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 1 circle element', () => {
|
|
24
|
+
const wrapper = mount(FilledCircle);
|
|
25
|
+
const circles = wrapper.findAll('circle');
|
|
26
|
+
expect(circles).toHaveLength(1);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe('Circle Properties', () => {
|
|
31
|
+
it('circle is centered in viewBox', () => {
|
|
32
|
+
const wrapper = mount(FilledCircle);
|
|
33
|
+
const circle = wrapper.find('circle');
|
|
34
|
+
|
|
35
|
+
expect(circle.attributes('cx')).toBe('8');
|
|
36
|
+
expect(circle.attributes('cy')).toBe('8');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('circle fills entire viewBox', () => {
|
|
40
|
+
const wrapper = mount(FilledCircle);
|
|
41
|
+
const circle = wrapper.find('circle');
|
|
42
|
+
|
|
43
|
+
expect(circle.attributes('r')).toBe('8');
|
|
44
|
+
// With radius 8 and center at (8,8), circle spans 0-16 in both dimensions
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('circle has correct fill color', () => {
|
|
48
|
+
const wrapper = mount(FilledCircle);
|
|
49
|
+
const circle = wrapper.find('circle');
|
|
50
|
+
|
|
51
|
+
expect(circle.attributes('fill')).toBe('#C1C1C2');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('circle has no stroke', () => {
|
|
55
|
+
const wrapper = mount(FilledCircle);
|
|
56
|
+
const circle = wrapper.find('circle');
|
|
57
|
+
|
|
58
|
+
expect(circle.attributes('stroke')).toBeUndefined();
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe('Visual Properties', () => {
|
|
63
|
+
it('uses gray fill color', () => {
|
|
64
|
+
const wrapper = mount(FilledCircle);
|
|
65
|
+
const circle = wrapper.find('circle');
|
|
66
|
+
|
|
67
|
+
expect(circle.attributes('fill')).toBe('#C1C1C2');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('svg container has no default fill', () => {
|
|
71
|
+
const wrapper = mount(FilledCircle);
|
|
72
|
+
const svg = wrapper.find('svg');
|
|
73
|
+
|
|
74
|
+
expect(svg.attributes('fill')).toBe('none');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('creates solid filled appearance', () => {
|
|
78
|
+
const wrapper = mount(FilledCircle);
|
|
79
|
+
const circle = wrapper.find('circle');
|
|
80
|
+
|
|
81
|
+
// Should have fill but no stroke for solid appearance
|
|
82
|
+
expect(circle.attributes('fill')).toBeTruthy();
|
|
83
|
+
expect(circle.attributes('stroke')).toBeUndefined();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe('Dimensions', () => {
|
|
88
|
+
it('uses compact 16x16 size', () => {
|
|
89
|
+
const wrapper = mount(FilledCircle);
|
|
90
|
+
const svg = wrapper.find('svg');
|
|
91
|
+
|
|
92
|
+
expect(svg.attributes('width')).toBe('16');
|
|
93
|
+
expect(svg.attributes('height')).toBe('16');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('maintains square aspect ratio', () => {
|
|
97
|
+
const wrapper = mount(FilledCircle);
|
|
98
|
+
const svg = wrapper.find('svg');
|
|
99
|
+
|
|
100
|
+
const width = svg.attributes('width');
|
|
101
|
+
const height = svg.attributes('height');
|
|
102
|
+
expect(width).toBe(height);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('has matching viewBox dimensions', () => {
|
|
106
|
+
const wrapper = mount(FilledCircle);
|
|
107
|
+
const svg = wrapper.find('svg');
|
|
108
|
+
|
|
109
|
+
expect(svg.attributes('viewBox')).toBe('0 0 16 16');
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe('Circle Geometry', () => {
|
|
114
|
+
it('circle is perfectly centered', () => {
|
|
115
|
+
const wrapper = mount(FilledCircle);
|
|
116
|
+
const circle = wrapper.find('circle');
|
|
117
|
+
|
|
118
|
+
const cx = parseInt(circle.attributes('cx'));
|
|
119
|
+
const cy = parseInt(circle.attributes('cy'));
|
|
120
|
+
const r = parseInt(circle.attributes('r'));
|
|
121
|
+
|
|
122
|
+
// Center should be at half the viewBox dimensions
|
|
123
|
+
expect(cx).toBe(8);
|
|
124
|
+
expect(cy).toBe(8);
|
|
125
|
+
expect(r).toBe(8);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('circle touches all edges of viewBox', () => {
|
|
129
|
+
const wrapper = mount(FilledCircle);
|
|
130
|
+
const circle = wrapper.find('circle');
|
|
131
|
+
|
|
132
|
+
const cx = parseInt(circle.attributes('cx'));
|
|
133
|
+
const cy = parseInt(circle.attributes('cy'));
|
|
134
|
+
const r = parseInt(circle.attributes('r'));
|
|
135
|
+
|
|
136
|
+
// Circle should extend from 0 to 16 in both dimensions
|
|
137
|
+
expect(cx - r).toBe(0); // Left edge
|
|
138
|
+
expect(cx + r).toBe(16); // Right edge
|
|
139
|
+
expect(cy - r).toBe(0); // Top edge
|
|
140
|
+
expect(cy + r).toBe(16); // Bottom edge
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('forms perfect circle', () => {
|
|
144
|
+
const wrapper = mount(FilledCircle);
|
|
145
|
+
const circle = wrapper.find('circle');
|
|
146
|
+
|
|
147
|
+
// All radii should be equal
|
|
148
|
+
const r = circle.attributes('r');
|
|
149
|
+
expect(r).toBe('8');
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe('Component Structure', () => {
|
|
154
|
+
it('suitable for UI indicators', () => {
|
|
155
|
+
const wrapper = mount(FilledCircle);
|
|
156
|
+
const svg = wrapper.find('svg');
|
|
157
|
+
|
|
158
|
+
// Small size appropriate for bullets, status indicators, etc.
|
|
159
|
+
expect(svg.attributes('width')).toBe('16');
|
|
160
|
+
expect(svg.attributes('height')).toBe('16');
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('uses neutral gray color', () => {
|
|
164
|
+
const wrapper = mount(FilledCircle);
|
|
165
|
+
const circle = wrapper.find('circle');
|
|
166
|
+
|
|
167
|
+
// Gray color suggests neutral/inactive state
|
|
168
|
+
expect(circle.attributes('fill')).toBe('#C1C1C2');
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
describe('Accessibility', () => {
|
|
173
|
+
it('svg is properly structured for screen readers', () => {
|
|
174
|
+
const wrapper = mount(FilledCircle);
|
|
175
|
+
const svg = wrapper.find('svg');
|
|
176
|
+
|
|
177
|
+
expect(svg.element.tagName.toLowerCase()).toBe('svg');
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('simple structure for clear recognition', () => {
|
|
181
|
+
const wrapper = mount(FilledCircle);
|
|
182
|
+
|
|
183
|
+
// Should have minimal, clear structure
|
|
184
|
+
expect(wrapper.findAll('circle')).toHaveLength(1);
|
|
185
|
+
expect(wrapper.findAll('path')).toHaveLength(0);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe('Component Integration', () => {
|
|
190
|
+
it('can be mounted without props', () => {
|
|
191
|
+
expect(() => {
|
|
192
|
+
mount(FilledCircle);
|
|
193
|
+
}).not.toThrow();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('renders consistently on multiple mounts', () => {
|
|
197
|
+
const wrapper1 = mount(FilledCircle);
|
|
198
|
+
const wrapper2 = mount(FilledCircle);
|
|
199
|
+
|
|
200
|
+
expect(wrapper1.html()).toBe(wrapper2.html());
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('maintains circle integrity', () => {
|
|
204
|
+
const wrapper = mount(FilledCircle);
|
|
205
|
+
const circle = wrapper.find('circle');
|
|
206
|
+
|
|
207
|
+
expect(circle.exists()).toBe(true);
|
|
208
|
+
expect(circle.attributes('cx')).toBeTruthy();
|
|
209
|
+
expect(circle.attributes('cy')).toBeTruthy();
|
|
210
|
+
expect(circle.attributes('r')).toBeTruthy();
|
|
211
|
+
expect(circle.attributes('fill')).toBeTruthy();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('suitable for various UI contexts', () => {
|
|
215
|
+
const wrapper = mount(FilledCircle);
|
|
216
|
+
|
|
217
|
+
// Small, neutral, and simple - good for:
|
|
218
|
+
// - List bullets
|
|
219
|
+
// - Status indicators
|
|
220
|
+
// - Form elements
|
|
221
|
+
// - Navigation dots
|
|
222
|
+
expect(wrapper.find('svg').attributes('width')).toBe('16');
|
|
223
|
+
expect(wrapper.find('circle').attributes('fill')).toBe('#C1C1C2');
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
describe('Icon Semantics', () => {
|
|
228
|
+
it('represents filled state or bullet point', () => {
|
|
229
|
+
const wrapper = mount(FilledCircle);
|
|
230
|
+
const circle = wrapper.find('circle');
|
|
231
|
+
|
|
232
|
+
// Solid fill suggests "filled" or "active" state
|
|
233
|
+
expect(circle.attributes('fill')).toBe('#C1C1C2');
|
|
234
|
+
expect(circle.attributes('stroke')).toBeUndefined();
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('uses appropriate size for inline usage', () => {
|
|
238
|
+
const wrapper = mount(FilledCircle);
|
|
239
|
+
const svg = wrapper.find('svg');
|
|
240
|
+
|
|
241
|
+
// 16px is good size for inline with text or as small indicator
|
|
242
|
+
expect(svg.attributes('width')).toBe('16');
|
|
243
|
+
expect(svg.attributes('height')).toBe('16');
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('neutral color suggests inactive or default state', () => {
|
|
247
|
+
const wrapper = mount(FilledCircle);
|
|
248
|
+
const circle = wrapper.find('circle');
|
|
249
|
+
|
|
250
|
+
// Gray color typically indicates neutral/inactive state
|
|
251
|
+
const fillColor = circle.attributes('fill');
|
|
252
|
+
expect(fillColor).toBe('#C1C1C2');
|
|
253
|
+
expect(fillColor.toLowerCase()).toMatch(/^#[c-f]/); // Grayish color range
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
describe('Visual Design', () => {
|
|
258
|
+
it('provides clear visual weight', () => {
|
|
259
|
+
const wrapper = mount(FilledCircle);
|
|
260
|
+
const circle = wrapper.find('circle');
|
|
261
|
+
|
|
262
|
+
// Solid fill provides clear visual presence
|
|
263
|
+
expect(circle.attributes('fill')).toBeTruthy();
|
|
264
|
+
expect(circle.attributes('fill')).not.toBe('none');
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('maintains simplicity for scalability', () => {
|
|
268
|
+
const wrapper = mount(FilledCircle);
|
|
269
|
+
|
|
270
|
+
// Simple single-element design scales well
|
|
271
|
+
expect(wrapper.findAll('*')).toHaveLength(2); // svg + circle
|
|
272
|
+
expect(wrapper.find('circle').exists()).toBe(true);
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
275
|
});
|