@zap-wunschlachen/wl-shared-components 1.0.35 → 1.0.38
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/App.vue +2 -7
- package/package.json +1 -1
- package/src/components/Audio/Waveform.vue +1 -0
- package/src/components/Button/Button.vue +39 -1
- package/src/components/CheckBox/CheckBox.css +29 -0
- package/src/components/CheckBox/Checkbox.vue +10 -2
- package/src/components/Dialog/Dialog.vue +14 -5
- package/src/components/Input/Input.vue +8 -2
- package/src/components/Loader/Loader.css +20 -0
- package/src/components/Loader/Loader.vue +1 -0
- package/src/components/OtpInput/OtpInput.vue +1 -1
- package/src/components/Select/Select.vue +1 -0
- package/src/components/StagingBanner/StagingBanner.css +19 -0
- package/src/components/StagingBanner/StagingBanner.vue +82 -0
- package/src/components/accessibility.css +218 -0
- package/src/components/index.ts +1 -0
- package/tests/unit/accessibility/component-a11y.spec.ts +469 -0
- package/tests/unit/components/Accordion/AccordionGroup.spec.ts +228 -0
- package/tests/unit/components/Accordion/AccordionItem.spec.ts +292 -0
- package/tests/unit/components/Appointment/AnamneseNotification.spec.ts +176 -0
- package/tests/unit/components/Background/Background.spec.ts +177 -0
- package/tests/unit/components/ErrorPage/ErrorPage.spec.ts +313 -0
- package/tests/unit/components/ErrorPage/ErrorPageLogo.spec.ts +153 -0
- package/tests/unit/components/Icons/AdvanceAppointments.spec.ts +61 -0
- package/tests/unit/components/Icons/Logo.spec.ts +228 -0
- package/tests/unit/components/Icons/MiniLogo.spec.ts +38 -0
- package/tests/unit/components/Icons/SolidArrowRight.spec.ts +49 -0
- package/tests/unit/components/Loader/Loader.spec.ts +197 -0
- package/tests/unit/components/MaintenanceBanner/MaintenanceBanner.spec.ts +302 -0
- package/tests/unit/utils/accessibility.spec.ts +318 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import Logo from '@components/Icons/Logo.vue';
|
|
4
|
+
|
|
5
|
+
// Mock siteColors
|
|
6
|
+
vi.mock('@/utils/index', () => ({
|
|
7
|
+
siteColors: {
|
|
8
|
+
domain: 'domain-dental',
|
|
9
|
+
font_color_code: '#172774'
|
|
10
|
+
}
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
describe('Logo', () => {
|
|
14
|
+
describe('Default Behavior', () => {
|
|
15
|
+
it('renders SVG element', () => {
|
|
16
|
+
const wrapper = mount(Logo);
|
|
17
|
+
expect(wrapper.find('svg').exists()).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('renders with default dimensions', () => {
|
|
21
|
+
const wrapper = mount(Logo);
|
|
22
|
+
const svg = wrapper.find('svg');
|
|
23
|
+
expect(svg.attributes('width')).toBe('120');
|
|
24
|
+
expect(svg.attributes('height')).toBe('30');
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe('Props', () => {
|
|
29
|
+
it('accepts custom width', () => {
|
|
30
|
+
const wrapper = mount(Logo, {
|
|
31
|
+
props: { width: '200' }
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const svg = wrapper.find('svg');
|
|
35
|
+
expect(svg.attributes('width')).toBe('200');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('accepts custom height', () => {
|
|
39
|
+
const wrapper = mount(Logo, {
|
|
40
|
+
props: { height: '50' }
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const svg = wrapper.find('svg');
|
|
44
|
+
expect(svg.attributes('height')).toBe('50');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('accepts custom domain', () => {
|
|
48
|
+
const wrapper = mount(Logo, {
|
|
49
|
+
props: { domain: 'domain-cocoon' }
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
expect(wrapper.vm.domain).toBe('domain-cocoon');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('uses siteColors domain when domain prop is empty', () => {
|
|
56
|
+
const wrapper = mount(Logo, {
|
|
57
|
+
props: { domain: '' }
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Should fall back to siteColors domain (dental)
|
|
61
|
+
const svg = wrapper.find('svg');
|
|
62
|
+
expect(svg.attributes('viewBox')).toBe('0 0 120 43');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('Domain-specific Rendering', () => {
|
|
67
|
+
it('renders dental logo by default', () => {
|
|
68
|
+
const wrapper = mount(Logo);
|
|
69
|
+
|
|
70
|
+
const svg = wrapper.find('svg');
|
|
71
|
+
expect(svg.attributes('viewBox')).toBe('0 0 120 43');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('renders cocoon logo when domain is domain-cocoon', () => {
|
|
75
|
+
const wrapper = mount(Logo, {
|
|
76
|
+
props: { domain: 'domain-cocoon' }
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const svg = wrapper.find('svg');
|
|
80
|
+
expect(svg.attributes('viewBox')).toBe('0 0 124 41');
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('SVG Structure', () => {
|
|
85
|
+
it('has proper viewBox attribute', () => {
|
|
86
|
+
const wrapper = mount(Logo);
|
|
87
|
+
const svg = wrapper.find('svg');
|
|
88
|
+
expect(svg.attributes('viewBox')).toBeDefined();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('contains path elements', () => {
|
|
92
|
+
const wrapper = mount(Logo);
|
|
93
|
+
const paths = wrapper.findAll('path');
|
|
94
|
+
expect(paths.length).toBeGreaterThan(0);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('has fill attribute on paths', () => {
|
|
98
|
+
const wrapper = mount(Logo);
|
|
99
|
+
const paths = wrapper.findAll('path');
|
|
100
|
+
|
|
101
|
+
paths.forEach(path => {
|
|
102
|
+
expect(path.attributes('fill')).toBeDefined();
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('Accessibility', () => {
|
|
108
|
+
it('SVG can be used as decorative image', () => {
|
|
109
|
+
// By default the Logo should render an SVG without an accessible name
|
|
110
|
+
const wrapper = mount(Logo);
|
|
111
|
+
const svg = wrapper.find('svg');
|
|
112
|
+
expect(svg.exists()).toBe(true);
|
|
113
|
+
|
|
114
|
+
// Decorative by default: no aria-label and should be hidden from assistive tech
|
|
115
|
+
expect(svg.attributes('aria-label')).toBeUndefined();
|
|
116
|
+
// If the component is used decoratively, authors may add aria-hidden
|
|
117
|
+
// but by default we ensure no accessible name is present
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('exposes accessible name when labelled via attributes', () => {
|
|
121
|
+
const wrapper = mount(Logo, {
|
|
122
|
+
attrs: {
|
|
123
|
+
'aria-label': 'Company Logo',
|
|
124
|
+
role: 'img'
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const svg = wrapper.find('svg');
|
|
129
|
+
expect(svg.exists()).toBe(true);
|
|
130
|
+
expect(svg.attributes('aria-label')).toBe('Company Logo');
|
|
131
|
+
expect(svg.attributes('role')).toBe('img');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('has appropriate namespace', () => {
|
|
135
|
+
const wrapper = mount(Logo);
|
|
136
|
+
const svg = wrapper.find('svg');
|
|
137
|
+
expect(svg.attributes('xmlns')).toBe('http://www.w3.org/2000/svg');
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('renders without visual errors', () => {
|
|
141
|
+
const wrapper = mount(Logo, {
|
|
142
|
+
props: {
|
|
143
|
+
width: '100',
|
|
144
|
+
height: '25'
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
expect(wrapper.find('svg').exists()).toBe(true);
|
|
149
|
+
expect(wrapper.findAll('path').length).toBeGreaterThan(0);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe('Theming', () => {
|
|
154
|
+
it('applies font color from siteColors', () => {
|
|
155
|
+
const wrapper = mount(Logo);
|
|
156
|
+
const paths = wrapper.findAll('path');
|
|
157
|
+
|
|
158
|
+
// All paths should use the theme color
|
|
159
|
+
expect(paths.length).toBeGreaterThan(0);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
describe('Edge Cases', () => {
|
|
164
|
+
it('handles zero dimensions', () => {
|
|
165
|
+
const wrapper = mount(Logo, {
|
|
166
|
+
props: {
|
|
167
|
+
width: '0',
|
|
168
|
+
height: '0'
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const svg = wrapper.find('svg');
|
|
173
|
+
expect(svg.attributes('width')).toBe('0');
|
|
174
|
+
expect(svg.attributes('height')).toBe('0');
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('handles very large dimensions', () => {
|
|
178
|
+
const wrapper = mount(Logo, {
|
|
179
|
+
props: {
|
|
180
|
+
width: '1000',
|
|
181
|
+
height: '500'
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
const svg = wrapper.find('svg');
|
|
186
|
+
expect(svg.attributes('width')).toBe('1000');
|
|
187
|
+
expect(svg.attributes('height')).toBe('500');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('handles empty string domain', () => {
|
|
191
|
+
const wrapper = mount(Logo, {
|
|
192
|
+
props: { domain: '' }
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
expect(wrapper.find('svg').exists()).toBe(true);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('handles unknown domain gracefully', () => {
|
|
199
|
+
const wrapper = mount(Logo, {
|
|
200
|
+
props: { domain: 'unknown-domain' }
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Should still render (falls back to dental)
|
|
204
|
+
expect(wrapper.find('svg').exists()).toBe(true);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
describe('Size Variations', () => {
|
|
209
|
+
const sizes = [
|
|
210
|
+
{ width: '50', height: '15' },
|
|
211
|
+
{ width: '120', height: '30' },
|
|
212
|
+
{ width: '200', height: '50' },
|
|
213
|
+
{ width: '400', height: '100' }
|
|
214
|
+
];
|
|
215
|
+
|
|
216
|
+
sizes.forEach(({ width, height }) => {
|
|
217
|
+
it(`renders correctly at ${width}x${height}`, () => {
|
|
218
|
+
const wrapper = mount(Logo, {
|
|
219
|
+
props: { width, height }
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const svg = wrapper.find('svg');
|
|
223
|
+
expect(svg.attributes('width')).toBe(width);
|
|
224
|
+
expect(svg.attributes('height')).toBe(height);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import MiniLogo from '@components/Icons/MiniLogo.vue';
|
|
4
|
+
|
|
5
|
+
// Mock siteColors
|
|
6
|
+
vi.mock('@/utils/index', () => ({
|
|
7
|
+
siteColors: {
|
|
8
|
+
font_color_code: '#172774'
|
|
9
|
+
}
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
describe('MiniLogo', () => {
|
|
13
|
+
describe('Default Behavior', () => {
|
|
14
|
+
it('renders SVG element', () => {
|
|
15
|
+
const wrapper = mount(MiniLogo);
|
|
16
|
+
expect(wrapper.find('svg').exists()).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('Accessibility', () => {
|
|
21
|
+
it('has accessible attributes', () => {
|
|
22
|
+
const wrapper = mount(MiniLogo);
|
|
23
|
+
const svg = wrapper.find('svg');
|
|
24
|
+
expect(svg.exists()).toBe(true);
|
|
25
|
+
// Add checks for actual accessibility attributes:
|
|
26
|
+
// expect(svg.attributes('role')).toBe('img');
|
|
27
|
+
// expect(svg.attributes('aria-label')).toBeTruthy();
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('Visual Structure', () => {
|
|
32
|
+
it('contains path elements for logo rendering', () => {
|
|
33
|
+
const wrapper = mount(MiniLogo);
|
|
34
|
+
const paths = wrapper.findAll('path');
|
|
35
|
+
expect(paths.length).toBeGreaterThan(0);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import SolidArrowRight from '@components/Icons/SolidArrowRight.vue';
|
|
4
|
+
|
|
5
|
+
// Mock siteColors if used
|
|
6
|
+
vi.mock('@/utils/index', () => ({
|
|
7
|
+
siteColors: {
|
|
8
|
+
font_color_code: '#172774'
|
|
9
|
+
}
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
describe('SolidArrowRight', () => {
|
|
13
|
+
describe('Default Behavior', () => {
|
|
14
|
+
it('renders SVG element', () => {
|
|
15
|
+
const wrapper = mount(SolidArrowRight);
|
|
16
|
+
expect(wrapper.find('svg').exists()).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('Accessibility', () => {
|
|
21
|
+
it('SVG is present for icon display', () => {
|
|
22
|
+
const wrapper = mount(SolidArrowRight);
|
|
23
|
+
expect(wrapper.find('svg').exists()).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('icon represents directional arrow', () => {
|
|
27
|
+
const wrapper = mount(SolidArrowRight);
|
|
28
|
+
// Arrow icons are typically used for navigation
|
|
29
|
+
expect(wrapper.find('svg').exists()).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('Visual Structure', () => {
|
|
34
|
+
it('has proper SVG namespace', () => {
|
|
35
|
+
const wrapper = mount(SolidArrowRight);
|
|
36
|
+
const svg = wrapper.find('svg');
|
|
37
|
+
expect(svg.attributes('xmlns')).toBe('http://www.w3.org/2000/svg');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('contains path or polygon elements', () => {
|
|
41
|
+
const wrapper = mount(SolidArrowRight);
|
|
42
|
+
const paths = wrapper.findAll('path');
|
|
43
|
+
const polygons = wrapper.findAll('polygon');
|
|
44
|
+
|
|
45
|
+
// Icon should have visual elements
|
|
46
|
+
expect(paths.length + polygons.length).toBeGreaterThan(0);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import Loader from '@components/Loader/Loader.vue';
|
|
4
|
+
|
|
5
|
+
// Mock siteColors
|
|
6
|
+
vi.mock('@/utils/index', () => ({
|
|
7
|
+
siteColors: {
|
|
8
|
+
font_color_code: '#172774'
|
|
9
|
+
}
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
describe('Loader', () => {
|
|
13
|
+
describe('Default Behavior', () => {
|
|
14
|
+
it('renders with default props', () => {
|
|
15
|
+
const wrapper = mount(Loader);
|
|
16
|
+
|
|
17
|
+
expect(wrapper.find('.loader-container').exists()).toBe(true);
|
|
18
|
+
expect(wrapper.find('.loader-svg').exists()).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('renders spinner SVG', () => {
|
|
22
|
+
const wrapper = mount(Loader);
|
|
23
|
+
expect(wrapper.find('svg').exists()).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('applies default size of 96px', () => {
|
|
27
|
+
const wrapper = mount(Loader);
|
|
28
|
+
expect(wrapper.vm.size).toBe(96);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('Props', () => {
|
|
33
|
+
it('accepts custom size prop', () => {
|
|
34
|
+
const wrapper = mount(Loader, {
|
|
35
|
+
props: {
|
|
36
|
+
size: 48
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
expect(wrapper.vm.size).toBe(48);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('applies size to SVG element', () => {
|
|
44
|
+
const wrapper = mount(Loader, {
|
|
45
|
+
props: {
|
|
46
|
+
size: 64
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const svg = wrapper.find('.loader-svg');
|
|
51
|
+
expect(svg.attributes('style')).toContain('width: 64px');
|
|
52
|
+
expect(svg.attributes('style')).toContain('height: 64px');
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('Accessibility', () => {
|
|
57
|
+
it('has role="alert" for screen readers', () => {
|
|
58
|
+
const wrapper = mount(Loader);
|
|
59
|
+
expect(wrapper.find('[role="alert"]').exists()).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('has aria-live="assertive" for immediate announcement', () => {
|
|
63
|
+
const wrapper = mount(Loader);
|
|
64
|
+
expect(wrapper.find('[aria-live="assertive"]').exists()).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('has aria-busy="true" to indicate loading state', () => {
|
|
68
|
+
const wrapper = mount(Loader);
|
|
69
|
+
expect(wrapper.find('[aria-busy="true"]').exists()).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('has role="status" for the spinner', () => {
|
|
73
|
+
const wrapper = mount(Loader);
|
|
74
|
+
expect(wrapper.find('[role="status"]').exists()).toBe(true);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('has aria-hidden="true" on decorative SVG', () => {
|
|
78
|
+
const wrapper = mount(Loader);
|
|
79
|
+
const svg = wrapper.find('svg');
|
|
80
|
+
expect(svg.attributes('aria-hidden')).toBe('true');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('provides proper semantic structure for assistive technologies', () => {
|
|
84
|
+
const wrapper = mount(Loader);
|
|
85
|
+
|
|
86
|
+
// Container announces loading state
|
|
87
|
+
const container = wrapper.find('.loader-container');
|
|
88
|
+
expect(container.attributes('role')).toBe('alert');
|
|
89
|
+
expect(container.attributes('aria-live')).toBe('assertive');
|
|
90
|
+
expect(container.attributes('aria-busy')).toBe('true');
|
|
91
|
+
|
|
92
|
+
// Inner status provides spinner context
|
|
93
|
+
const status = wrapper.find('[role="status"]');
|
|
94
|
+
expect(status.exists()).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('follows WCAG 2.1 guidelines for loading indicators', () => {
|
|
98
|
+
const wrapper = mount(Loader);
|
|
99
|
+
|
|
100
|
+
// Should have proper ARIA attributes
|
|
101
|
+
expect(wrapper.find('[aria-busy]').exists()).toBe(true);
|
|
102
|
+
expect(wrapper.find('[aria-live]').exists()).toBe(true);
|
|
103
|
+
|
|
104
|
+
// SVG should be hidden from screen readers
|
|
105
|
+
expect(wrapper.find('svg[aria-hidden="true"]').exists()).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe('Visual Structure', () => {
|
|
110
|
+
it('has loader-container wrapper', () => {
|
|
111
|
+
const wrapper = mount(Loader);
|
|
112
|
+
expect(wrapper.find('.loader-container').exists()).toBe(true);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('has loader-content for centering', () => {
|
|
116
|
+
const wrapper = mount(Loader);
|
|
117
|
+
expect(wrapper.find('.loader-content').exists()).toBe(true);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('contains animated spinner arc', () => {
|
|
121
|
+
const wrapper = mount(Loader);
|
|
122
|
+
expect(wrapper.find('.loader-spinner-arc').exists()).toBe(true);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe('SVG Content', () => {
|
|
127
|
+
it('renders SVG with proper viewBox', () => {
|
|
128
|
+
const wrapper = mount(Loader);
|
|
129
|
+
const svg = wrapper.find('svg');
|
|
130
|
+
expect(svg.attributes('viewBox')).toBe('0 0 100 101');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('renders path elements for spinner', () => {
|
|
134
|
+
const wrapper = mount(Loader);
|
|
135
|
+
const paths = wrapper.findAll('path');
|
|
136
|
+
expect(paths.length).toBeGreaterThan(0);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('renders W logo in the center', () => {
|
|
140
|
+
const wrapper = mount(Loader);
|
|
141
|
+
// The W logo is inside a g element
|
|
142
|
+
const gElements = wrapper.findAll('g');
|
|
143
|
+
expect(gElements.length).toBeGreaterThan(0);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe('Size Variations', () => {
|
|
148
|
+
it('handles small size (24px)', () => {
|
|
149
|
+
const wrapper = mount(Loader, {
|
|
150
|
+
props: { size: 24 }
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const svg = wrapper.find('.loader-svg');
|
|
154
|
+
expect(svg.attributes('style')).toContain('width: 24px');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('handles large size (200px)', () => {
|
|
158
|
+
const wrapper = mount(Loader, {
|
|
159
|
+
props: { size: 200 }
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const svg = wrapper.find('.loader-svg');
|
|
163
|
+
expect(svg.attributes('style')).toContain('width: 200px');
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('handles zero size gracefully', () => {
|
|
167
|
+
const wrapper = mount(Loader, {
|
|
168
|
+
props: { size: 0 }
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
expect(wrapper.vm.size).toBe(0);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
describe('Edge Cases', () => {
|
|
176
|
+
it('renders without props', () => {
|
|
177
|
+
const wrapper = mount(Loader);
|
|
178
|
+
expect(wrapper.find('.loader-container').exists()).toBe(true);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('maintains structure with undefined size', () => {
|
|
182
|
+
const wrapper = mount(Loader, {
|
|
183
|
+
props: { size: undefined }
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Should fall back to default size
|
|
187
|
+
expect(wrapper.vm.size).toBe(96);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe('Animation', () => {
|
|
192
|
+
it('has animated spinner arc class', () => {
|
|
193
|
+
const wrapper = mount(Loader);
|
|
194
|
+
expect(wrapper.find('.loader-spinner-arc').exists()).toBe(true);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
});
|