@datametria/vue-components 1.2.0 → 2.0.1
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/README.md +548 -657
- package/dist/index.es.js +2353 -1364
- package/dist/index.umd.js +10 -10
- package/dist/vue-components.css +1 -1
- package/package.json +102 -98
- package/src/components/DatametriaAlert.vue +137 -137
- package/src/components/DatametriaAutocomplete.vue +184 -138
- package/src/components/DatametriaAvatar.vue +177 -33
- package/src/components/DatametriaBadge.vue +98 -98
- package/src/components/DatametriaBreadcrumb.vue +21 -21
- package/src/components/DatametriaButton.vue +177 -165
- package/src/components/DatametriaCard.vue +12 -12
- package/src/components/DatametriaCheckbox.vue +8 -8
- package/src/components/DatametriaChip.vue +145 -149
- package/src/components/DatametriaContainer.vue +4 -4
- package/src/components/DatametriaDatePicker.vue +686 -68
- package/src/components/DatametriaDivider.vue +13 -13
- package/src/components/DatametriaFileUpload.vue +272 -140
- package/src/components/DatametriaGrid.vue +3 -3
- package/src/components/DatametriaInput.vue +15 -15
- package/src/components/DatametriaMenu.vue +604 -619
- package/src/components/DatametriaModal.vue +16 -16
- package/src/components/DatametriaNavbar.vue +230 -252
- package/src/components/DatametriaPasswordInput.vue +430 -0
- package/src/components/DatametriaProgress.vue +18 -18
- package/src/components/DatametriaRadio.vue +20 -20
- package/src/components/DatametriaSelect.vue +15 -15
- package/src/components/DatametriaSkeleton.vue +243 -239
- package/src/components/DatametriaSlider.vue +395 -407
- package/src/components/DatametriaSortableTable.vue +585 -0
- package/src/components/DatametriaSpinner.vue +7 -7
- package/src/components/DatametriaSwitch.vue +16 -16
- package/src/components/DatametriaTable.vue +14 -14
- package/src/components/DatametriaTextarea.vue +28 -28
- package/src/components/DatametriaTimePicker.vue +285 -285
- package/src/components/DatametriaToast.vue +176 -176
- package/src/components/DatametriaTooltip.vue +408 -408
- package/src/components/__tests__/DatametriaAlert.test.js +35 -35
- package/src/components/__tests__/DatametriaAlert.test.ts +190 -0
- package/src/components/__tests__/DatametriaAutocomplete.test.ts +180 -0
- package/src/components/__tests__/DatametriaAvatar.test.ts +152 -0
- package/src/components/__tests__/DatametriaBadge.test.js +29 -29
- package/src/components/__tests__/DatametriaBadge.test.ts +167 -0
- package/src/components/__tests__/DatametriaBreadcrumb.test.ts +75 -0
- package/src/components/__tests__/DatametriaButton.test.js +30 -30
- package/src/components/__tests__/DatametriaButton.test.ts +283 -0
- package/src/components/__tests__/DatametriaCard.test.ts +201 -0
- package/src/components/__tests__/DatametriaCheckbox.test.ts +47 -0
- package/src/components/__tests__/DatametriaChip.test.js +38 -38
- package/src/components/__tests__/DatametriaContainer.test.ts +52 -0
- package/src/components/__tests__/DatametriaDatePicker.test.ts +234 -0
- package/src/components/__tests__/DatametriaDivider.test.ts +54 -0
- package/src/components/__tests__/DatametriaFileUpload.test.ts +291 -0
- package/src/components/__tests__/DatametriaGrid.test.ts +31 -0
- package/src/components/__tests__/DatametriaInput.test.ts +72 -0
- package/src/components/__tests__/DatametriaMenu.test.ts +366 -0
- package/src/components/__tests__/DatametriaModal.test.ts +86 -0
- package/src/components/__tests__/DatametriaNavbar.test.js +48 -48
- package/src/components/__tests__/DatametriaNavbar.test.ts +203 -0
- package/src/components/__tests__/DatametriaPasswordInput.test.js +305 -0
- package/src/components/__tests__/DatametriaProgress.test.ts +90 -0
- package/src/components/__tests__/DatametriaRadio.test.ts +77 -0
- package/src/components/__tests__/DatametriaSelect.test.ts +77 -0
- package/src/components/__tests__/DatametriaSlider.test.ts +261 -0
- package/src/components/__tests__/DatametriaSortableTable.test.js +168 -0
- package/src/components/__tests__/DatametriaSpinner.test.ts +156 -0
- package/src/components/__tests__/DatametriaSwitch.test.ts +64 -0
- package/src/components/__tests__/DatametriaTable.test.ts +97 -0
- package/src/components/__tests__/DatametriaTextarea.test.ts +66 -0
- package/src/components/__tests__/DatametriaToast.test.js +48 -48
- package/src/components/__tests__/DatametriaToast.test.ts +99 -0
- package/src/composables/useAccessibilityScale.ts +94 -94
- package/src/composables/useBreakpoints.ts +82 -82
- package/src/composables/useHapticFeedback.ts +439 -439
- package/src/composables/useRipple.ts +218 -218
- package/src/index.ts +68 -61
- package/src/stories/Variants.stories.js +95 -95
- package/src/styles/design-tokens.css +623 -623
- package/src/theme/ThemeProvider.vue +96 -0
- package/src/theme/__tests__/ThemeProvider.test.ts +208 -0
- package/src/theme/__tests__/constants.test.ts +31 -0
- package/src/theme/__tests__/presets.test.ts +166 -0
- package/src/theme/__tests__/tokens.test.ts +155 -0
- package/src/theme/__tests__/types.test.ts +153 -0
- package/src/theme/__tests__/useTheme.test.ts +146 -0
- package/src/theme/constants.ts +14 -0
- package/src/theme/index.ts +12 -0
- package/src/theme/presets/datametria.ts +94 -0
- package/src/theme/presets/default.ts +94 -0
- package/src/theme/presets/index.ts +8 -0
- package/src/theme/tokens/colors.ts +28 -0
- package/src/theme/tokens/index.ts +47 -0
- package/src/theme/tokens/spacing.ts +21 -0
- package/src/theme/tokens/typography.ts +35 -0
- package/src/theme/types.ts +111 -0
- package/src/theme/useTheme.ts +28 -0
- package/src/types/index.ts +19 -0
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
2
|
-
import { mount } from '@vue/test-utils'
|
|
3
|
-
import DatametriaAlert from '../DatametriaAlert.vue'
|
|
4
|
-
|
|
5
|
-
describe('DatametriaAlert', () => {
|
|
6
|
-
it('renders with primary variant', () => {
|
|
7
|
-
const wrapper = mount(DatametriaAlert, {
|
|
8
|
-
props: {
|
|
9
|
-
variant: 'primary',
|
|
10
|
-
message: 'Test message'
|
|
11
|
-
}
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
expect(wrapper.classes()).toContain('datametria-alert--primary')
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
it('validates invalid variant in development', () => {
|
|
18
|
-
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
19
|
-
const originalEnv = process.env.NODE_ENV
|
|
20
|
-
process.env.NODE_ENV = 'development'
|
|
21
|
-
|
|
22
|
-
mount(DatametriaAlert, {
|
|
23
|
-
props: {
|
|
24
|
-
variant: 'invalid',
|
|
25
|
-
message: 'Test'
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
30
|
-
expect.stringContaining('[DatametriaAlert] Invalid variant "invalid"')
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
process.env.NODE_ENV = originalEnv
|
|
34
|
-
consoleSpy.mockRestore()
|
|
35
|
-
})
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest'
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import DatametriaAlert from '../DatametriaAlert.vue'
|
|
4
|
+
|
|
5
|
+
describe('DatametriaAlert', () => {
|
|
6
|
+
it('renders with primary variant', () => {
|
|
7
|
+
const wrapper = mount(DatametriaAlert, {
|
|
8
|
+
props: {
|
|
9
|
+
variant: 'primary',
|
|
10
|
+
message: 'Test message'
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
expect(wrapper.classes()).toContain('datametria-alert--primary')
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('validates invalid variant in development', () => {
|
|
18
|
+
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
19
|
+
const originalEnv = process.env.NODE_ENV
|
|
20
|
+
process.env.NODE_ENV = 'development'
|
|
21
|
+
|
|
22
|
+
mount(DatametriaAlert, {
|
|
23
|
+
props: {
|
|
24
|
+
variant: 'invalid',
|
|
25
|
+
message: 'Test'
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
30
|
+
expect.stringContaining('[DatametriaAlert] Invalid variant "invalid"')
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
process.env.NODE_ENV = originalEnv
|
|
34
|
+
consoleSpy.mockRestore()
|
|
35
|
+
})
|
|
36
36
|
})
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import DatametriaAlert from '../DatametriaAlert.vue'
|
|
4
|
+
|
|
5
|
+
describe('DatametriaAlert', () => {
|
|
6
|
+
// Rendering tests
|
|
7
|
+
it('renders with default props', () => {
|
|
8
|
+
const wrapper = mount(DatametriaAlert)
|
|
9
|
+
expect(wrapper.find('.datametria-alert').exists()).toBe(true)
|
|
10
|
+
expect(wrapper.find('.datametria-alert--info').exists()).toBe(true)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('renders with custom message', () => {
|
|
14
|
+
const wrapper = mount(DatametriaAlert, {
|
|
15
|
+
props: { message: 'Test message' }
|
|
16
|
+
})
|
|
17
|
+
expect(wrapper.text()).toContain('Test message')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('renders with title and message', () => {
|
|
21
|
+
const wrapper = mount(DatametriaAlert, {
|
|
22
|
+
props: {
|
|
23
|
+
title: 'Test Title',
|
|
24
|
+
message: 'Test message'
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
expect(wrapper.find('.datametria-alert__title').text()).toBe('Test Title')
|
|
28
|
+
expect(wrapper.find('.datametria-alert__message').text()).toBe('Test message')
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('renders slot content', () => {
|
|
32
|
+
const wrapper = mount(DatametriaAlert, {
|
|
33
|
+
slots: {
|
|
34
|
+
default: '<strong>Custom content</strong>'
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
expect(wrapper.html()).toContain('<strong>Custom content</strong>')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
// Variant tests
|
|
41
|
+
it('renders success variant', () => {
|
|
42
|
+
const wrapper = mount(DatametriaAlert, {
|
|
43
|
+
props: { variant: 'success' }
|
|
44
|
+
})
|
|
45
|
+
expect(wrapper.find('.datametria-alert--success').exists()).toBe(true)
|
|
46
|
+
expect(wrapper.text()).toContain('✓')
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('renders error variant', () => {
|
|
50
|
+
const wrapper = mount(DatametriaAlert, {
|
|
51
|
+
props: { variant: 'error' }
|
|
52
|
+
})
|
|
53
|
+
expect(wrapper.find('.datametria-alert--error').exists()).toBe(true)
|
|
54
|
+
expect(wrapper.text()).toContain('✕')
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('renders warning variant', () => {
|
|
58
|
+
const wrapper = mount(DatametriaAlert, {
|
|
59
|
+
props: { variant: 'warning' }
|
|
60
|
+
})
|
|
61
|
+
expect(wrapper.find('.datametria-alert--warning').exists()).toBe(true)
|
|
62
|
+
expect(wrapper.text()).toContain('⚠')
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('renders info variant', () => {
|
|
66
|
+
const wrapper = mount(DatametriaAlert, {
|
|
67
|
+
props: { variant: 'info' }
|
|
68
|
+
})
|
|
69
|
+
expect(wrapper.find('.datametria-alert--info').exists()).toBe(true)
|
|
70
|
+
expect(wrapper.text()).toContain('ℹ')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('renders primary variant', () => {
|
|
74
|
+
const wrapper = mount(DatametriaAlert, {
|
|
75
|
+
props: { variant: 'primary' }
|
|
76
|
+
})
|
|
77
|
+
expect(wrapper.find('.datametria-alert--primary').exists()).toBe(true)
|
|
78
|
+
expect(wrapper.text()).toContain('ℹ')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
// Closable tests
|
|
82
|
+
it('renders close button when closable', () => {
|
|
83
|
+
const wrapper = mount(DatametriaAlert, {
|
|
84
|
+
props: { closable: true }
|
|
85
|
+
})
|
|
86
|
+
expect(wrapper.find('.datametria-alert__close').exists()).toBe(true)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('does not render close button when not closable', () => {
|
|
90
|
+
const wrapper = mount(DatametriaAlert, {
|
|
91
|
+
props: { closable: false }
|
|
92
|
+
})
|
|
93
|
+
expect(wrapper.find('.datametria-alert__close').exists()).toBe(false)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('emits update:modelValue when close button clicked', async () => {
|
|
97
|
+
const wrapper = mount(DatametriaAlert, {
|
|
98
|
+
props: { closable: true }
|
|
99
|
+
})
|
|
100
|
+
await wrapper.find('.datametria-alert__close').trigger('click')
|
|
101
|
+
expect(wrapper.emitted('update:modelValue')).toBeTruthy()
|
|
102
|
+
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([false])
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
// v-model tests
|
|
106
|
+
it('shows alert when modelValue is true', () => {
|
|
107
|
+
const wrapper = mount(DatametriaAlert, {
|
|
108
|
+
props: { modelValue: true }
|
|
109
|
+
})
|
|
110
|
+
expect(wrapper.find('.datametria-alert').exists()).toBe(true)
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('hides alert when modelValue is false', () => {
|
|
114
|
+
const wrapper = mount(DatametriaAlert, {
|
|
115
|
+
props: { modelValue: false }
|
|
116
|
+
})
|
|
117
|
+
expect(wrapper.find('.datametria-alert').exists()).toBe(false)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
// CSS Variables tests
|
|
121
|
+
it('uses CSS variables for success variant', () => {
|
|
122
|
+
const wrapper = mount(DatametriaAlert, {
|
|
123
|
+
props: { variant: 'success' }
|
|
124
|
+
})
|
|
125
|
+
const alert = wrapper.find('.datametria-alert--success')
|
|
126
|
+
const style = getComputedStyle(alert.element)
|
|
127
|
+
|
|
128
|
+
// Verifica que as CSS variables estão sendo usadas
|
|
129
|
+
expect(alert.element.className).toContain('datametria-alert--success')
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
it('uses CSS variables for error variant', () => {
|
|
133
|
+
const wrapper = mount(DatametriaAlert, {
|
|
134
|
+
props: { variant: 'error' }
|
|
135
|
+
})
|
|
136
|
+
const alert = wrapper.find('.datametria-alert--error')
|
|
137
|
+
expect(alert.element.className).toContain('datametria-alert--error')
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('uses CSS variables for warning variant', () => {
|
|
141
|
+
const wrapper = mount(DatametriaAlert, {
|
|
142
|
+
props: { variant: 'warning' }
|
|
143
|
+
})
|
|
144
|
+
const alert = wrapper.find('.datametria-alert--warning')
|
|
145
|
+
expect(alert.element.className).toContain('datametria-alert--warning')
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('uses CSS variables for spacing and typography', () => {
|
|
149
|
+
const wrapper = mount(DatametriaAlert, {
|
|
150
|
+
props: {
|
|
151
|
+
title: 'Title',
|
|
152
|
+
message: 'Message'
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
// Verifica estrutura
|
|
157
|
+
expect(wrapper.find('.datametria-alert__icon').exists()).toBe(true)
|
|
158
|
+
expect(wrapper.find('.datametria-alert__content').exists()).toBe(true)
|
|
159
|
+
expect(wrapper.find('.datametria-alert__title').exists()).toBe(true)
|
|
160
|
+
expect(wrapper.find('.datametria-alert__message').exists()).toBe(true)
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
// Backward compatibility tests
|
|
164
|
+
it('works without ThemeProvider (fallback values)', () => {
|
|
165
|
+
const wrapper = mount(DatametriaAlert, {
|
|
166
|
+
props: {
|
|
167
|
+
variant: 'success',
|
|
168
|
+
title: 'Success',
|
|
169
|
+
message: 'Operation completed'
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
expect(wrapper.find('.datametria-alert--success').exists()).toBe(true)
|
|
174
|
+
expect(wrapper.text()).toContain('Success')
|
|
175
|
+
expect(wrapper.text()).toContain('Operation completed')
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
it('maintains visual consistency across variants', () => {
|
|
179
|
+
const variants: Array<'success' | 'error' | 'warning' | 'info' | 'primary'> = [
|
|
180
|
+
'success', 'error', 'warning', 'info', 'primary'
|
|
181
|
+
]
|
|
182
|
+
|
|
183
|
+
variants.forEach(variant => {
|
|
184
|
+
const wrapper = mount(DatametriaAlert, {
|
|
185
|
+
props: { variant }
|
|
186
|
+
})
|
|
187
|
+
expect(wrapper.find(`.datametria-alert--${variant}`).exists()).toBe(true)
|
|
188
|
+
})
|
|
189
|
+
})
|
|
190
|
+
})
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import DatametriaAutocomplete from '../DatametriaAutocomplete.vue'
|
|
4
|
+
import { datametriaTheme } from '../../theme/presets'
|
|
5
|
+
import { THEME_INJECTION_KEY } from '../../theme/constants'
|
|
6
|
+
|
|
7
|
+
const createWrapper = (props = {}, themeProps = {}) => {
|
|
8
|
+
return mount(DatametriaAutocomplete, {
|
|
9
|
+
props,
|
|
10
|
+
global: {
|
|
11
|
+
plugins: [{
|
|
12
|
+
install(app) {
|
|
13
|
+
app.provide(THEME_INJECTION_KEY, datametriaTheme)
|
|
14
|
+
}
|
|
15
|
+
}]
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe('DatametriaAutocomplete', () => {
|
|
21
|
+
const mockOptions = [
|
|
22
|
+
{ value: '1', label: 'Option 1' },
|
|
23
|
+
{ value: '2', label: 'Option 2' },
|
|
24
|
+
{ value: '3', label: 'Option 3' }
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
vi.clearAllMocks()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('renders correctly', () => {
|
|
32
|
+
const wrapper = createWrapper({ options: mockOptions })
|
|
33
|
+
expect(wrapper.find('.dm-autocomplete').exists()).toBe(true)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('applies theme colors correctly', () => {
|
|
37
|
+
const wrapper = createWrapper({ options: mockOptions })
|
|
38
|
+
expect(wrapper.find('.dm-autocomplete').exists()).toBe(true)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('shows options when focused', async () => {
|
|
42
|
+
const wrapper = createWrapper({ options: mockOptions })
|
|
43
|
+
const input = wrapper.find('.dm-autocomplete__input')
|
|
44
|
+
|
|
45
|
+
await input.trigger('focus')
|
|
46
|
+
expect(wrapper.find('.dm-autocomplete__dropdown').exists()).toBe(true)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('filters options based on search query', async () => {
|
|
50
|
+
const wrapper = createWrapper({ options: mockOptions })
|
|
51
|
+
const input = wrapper.find('.dm-autocomplete__input')
|
|
52
|
+
|
|
53
|
+
await input.setValue('Option 1')
|
|
54
|
+
await input.trigger('focus')
|
|
55
|
+
|
|
56
|
+
const options = wrapper.findAll('.dm-autocomplete__option')
|
|
57
|
+
expect(options).toHaveLength(1)
|
|
58
|
+
expect(options[0].text()).toBe('Option 1')
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('emits update:modelValue when option is selected', async () => {
|
|
62
|
+
const wrapper = createWrapper({ options: mockOptions })
|
|
63
|
+
const input = wrapper.find('.dm-autocomplete__input')
|
|
64
|
+
|
|
65
|
+
await input.trigger('focus')
|
|
66
|
+
const option = wrapper.find('.dm-autocomplete__option')
|
|
67
|
+
await option.trigger('click')
|
|
68
|
+
|
|
69
|
+
const autocomplete = wrapper.findComponent(DatametriaAutocomplete)
|
|
70
|
+
expect(autocomplete.emitted('update:modelValue')).toBeTruthy()
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('supports keyboard navigation', async () => {
|
|
74
|
+
const wrapper = createWrapper({ options: mockOptions })
|
|
75
|
+
const input = wrapper.find('.dm-autocomplete__input')
|
|
76
|
+
|
|
77
|
+
await input.trigger('focus')
|
|
78
|
+
await input.trigger('keydown', { key: 'ArrowDown' })
|
|
79
|
+
|
|
80
|
+
expect(wrapper.find('.dm-autocomplete__option--active').exists()).toBe(true)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('shows error state correctly', () => {
|
|
84
|
+
const wrapper = createWrapper({
|
|
85
|
+
options: mockOptions,
|
|
86
|
+
error: 'Required field'
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
expect(wrapper.find('.dm-autocomplete__input--error').exists()).toBe(true)
|
|
90
|
+
expect(wrapper.find('.dm-autocomplete__error').text()).toBe('Required field')
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('supports disabled state', () => {
|
|
94
|
+
const wrapper = createWrapper({
|
|
95
|
+
options: mockOptions,
|
|
96
|
+
disabled: true
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
const input = wrapper.find('.dm-autocomplete__input')
|
|
100
|
+
expect(input.attributes('disabled')).toBeDefined()
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('supports required field', () => {
|
|
104
|
+
const wrapper = createWrapper({
|
|
105
|
+
options: mockOptions,
|
|
106
|
+
required: true,
|
|
107
|
+
label: 'Test Label'
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
expect(wrapper.find('.dm-autocomplete__required').exists()).toBe(true)
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('supports custom placeholder', () => {
|
|
114
|
+
const placeholder = 'Search options...'
|
|
115
|
+
const wrapper = createWrapper({
|
|
116
|
+
options: mockOptions,
|
|
117
|
+
placeholder
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
const input = wrapper.find('.dm-autocomplete__input')
|
|
121
|
+
expect(input.attributes('placeholder')).toBe(placeholder)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('supports loading state', () => {
|
|
125
|
+
const wrapper = createWrapper({
|
|
126
|
+
options: mockOptions,
|
|
127
|
+
loading: true
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
expect(wrapper.find('.dm-autocomplete__loading').exists()).toBe(true)
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('supports no results message', async () => {
|
|
134
|
+
const wrapper = createWrapper({ options: mockOptions })
|
|
135
|
+
const input = wrapper.find('.dm-autocomplete__input')
|
|
136
|
+
|
|
137
|
+
await input.setValue('nonexistent')
|
|
138
|
+
await input.trigger('focus')
|
|
139
|
+
|
|
140
|
+
expect(wrapper.find('.dm-autocomplete__no-results').exists()).toBe(true)
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
it('closes dropdown when clicking outside', async () => {
|
|
144
|
+
const wrapper = createWrapper({ options: mockOptions })
|
|
145
|
+
const input = wrapper.find('.dm-autocomplete__input')
|
|
146
|
+
|
|
147
|
+
await input.trigger('focus')
|
|
148
|
+
expect(wrapper.find('.dm-autocomplete__dropdown').exists()).toBe(true)
|
|
149
|
+
|
|
150
|
+
// Simula clique fora do componente
|
|
151
|
+
document.body.click()
|
|
152
|
+
await new Promise(resolve => setTimeout(resolve, 250))
|
|
153
|
+
await wrapper.vm.$nextTick()
|
|
154
|
+
|
|
155
|
+
expect(wrapper.find('.dm-autocomplete__dropdown').exists()).toBe(false)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
it('supports multiple selection', async () => {
|
|
159
|
+
const wrapper = createWrapper({
|
|
160
|
+
options: mockOptions,
|
|
161
|
+
multiple: true
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
const input = wrapper.find('.dm-autocomplete__input')
|
|
165
|
+
await input.trigger('focus')
|
|
166
|
+
|
|
167
|
+
const option = wrapper.find('.dm-autocomplete__option')
|
|
168
|
+
await option.trigger('click')
|
|
169
|
+
|
|
170
|
+
expect(wrapper.find('.dm-autocomplete__tag').exists()).toBe(true)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
it('supports custom option template', () => {
|
|
174
|
+
const wrapper = createWrapper({
|
|
175
|
+
options: mockOptions.map(opt => ({ ...opt, description: `Description for ${opt.label}` }))
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
expect(wrapper.find('.dm-autocomplete').exists()).toBe(true)
|
|
179
|
+
})
|
|
180
|
+
})
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import DatametriaAvatar from '../DatametriaAvatar.vue'
|
|
4
|
+
import { datametriaTheme } from '../../theme/presets'
|
|
5
|
+
import { THEME_INJECTION_KEY } from '../../theme/constants'
|
|
6
|
+
|
|
7
|
+
const createWrapper = (props = {}, themeProps = {}) => {
|
|
8
|
+
return mount(DatametriaAvatar, {
|
|
9
|
+
props,
|
|
10
|
+
global: {
|
|
11
|
+
plugins: [{
|
|
12
|
+
install(app) {
|
|
13
|
+
app.provide(THEME_INJECTION_KEY, datametriaTheme)
|
|
14
|
+
}
|
|
15
|
+
}]
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe('DatametriaAvatar', () => {
|
|
21
|
+
it('renders correctly', () => {
|
|
22
|
+
const wrapper = createWrapper()
|
|
23
|
+
expect(wrapper.find('.dm-avatar').exists()).toBe(true)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('applies theme colors correctly', () => {
|
|
27
|
+
const wrapper = createWrapper()
|
|
28
|
+
expect(wrapper.find('.dm-avatar').exists()).toBe(true)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('displays image when src is provided', () => {
|
|
32
|
+
const src = 'https://example.com/avatar.jpg'
|
|
33
|
+
const wrapper = createWrapper({ src })
|
|
34
|
+
|
|
35
|
+
const img = wrapper.find('.dm-avatar__image')
|
|
36
|
+
expect(img.exists()).toBe(true)
|
|
37
|
+
expect(img.attributes('src')).toBe(src)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('displays initials when name is provided and no src', () => {
|
|
41
|
+
const name = 'John Doe'
|
|
42
|
+
const wrapper = createWrapper({ name })
|
|
43
|
+
|
|
44
|
+
expect(wrapper.find('.dm-avatar__initials').text()).toBe('JD')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('displays single initial for single name', () => {
|
|
48
|
+
const name = 'John'
|
|
49
|
+
const wrapper = createWrapper({ name })
|
|
50
|
+
|
|
51
|
+
expect(wrapper.find('.dm-avatar__initials').text()).toBe('J')
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('supports different sizes', () => {
|
|
55
|
+
const sizes = ['sm', 'md', 'lg', 'xl']
|
|
56
|
+
|
|
57
|
+
sizes.forEach(size => {
|
|
58
|
+
const wrapper = createWrapper({ size })
|
|
59
|
+
expect(wrapper.find(`.dm-avatar--${size}`).exists()).toBe(true)
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('supports different variants', () => {
|
|
64
|
+
const variants = ['circular', 'rounded', 'square']
|
|
65
|
+
|
|
66
|
+
variants.forEach(variant => {
|
|
67
|
+
const wrapper = createWrapper({ variant })
|
|
68
|
+
expect(wrapper.find(`.dm-avatar--${variant}`).exists()).toBe(true)
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('shows fallback icon when no src or name', () => {
|
|
73
|
+
const wrapper = createWrapper()
|
|
74
|
+
expect(wrapper.find('.dm-avatar__icon').exists()).toBe(true)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('handles image load error', async () => {
|
|
78
|
+
const wrapper = createWrapper({ src: 'invalid-url.jpg', name: 'John Doe' })
|
|
79
|
+
const img = wrapper.find('.dm-avatar__image')
|
|
80
|
+
|
|
81
|
+
await img.trigger('error')
|
|
82
|
+
expect(wrapper.find('.dm-avatar__initials').exists()).toBe(true)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('supports custom background color', () => {
|
|
86
|
+
const backgroundColor = '#ff0000'
|
|
87
|
+
const wrapper = createWrapper({ backgroundColor })
|
|
88
|
+
|
|
89
|
+
const avatar = wrapper.find('.dm-avatar')
|
|
90
|
+
const style = avatar.attributes('style')
|
|
91
|
+
// Aceita tanto HEX quanto RGB
|
|
92
|
+
expect(style).toMatch(/background-color: (#ff0000|rgb\(255, 0, 0\))/)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('supports custom text color', () => {
|
|
96
|
+
const textColor = '#ffffff'
|
|
97
|
+
const wrapper = createWrapper({ textColor, name: 'John Doe' })
|
|
98
|
+
|
|
99
|
+
const initials = wrapper.find('.dm-avatar__initials')
|
|
100
|
+
const style = initials.attributes('style')
|
|
101
|
+
// Aceita tanto HEX quanto RGB
|
|
102
|
+
expect(style).toMatch(/color: (#ffffff|rgb\(255, 255, 255\))/)
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('supports clickable avatar', async () => {
|
|
106
|
+
const wrapper = createWrapper({ clickable: true })
|
|
107
|
+
const avatar = wrapper.find('.dm-avatar')
|
|
108
|
+
|
|
109
|
+
expect(avatar.classes()).toContain('dm-avatar--clickable')
|
|
110
|
+
|
|
111
|
+
await avatar.trigger('click')
|
|
112
|
+
const avatarComponent = wrapper.findComponent(DatametriaAvatar)
|
|
113
|
+
expect(avatarComponent.emitted('click')).toBeTruthy()
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('supports badge/status indicator', () => {
|
|
117
|
+
const wrapper = createWrapper({ badge: true, status: 'online' })
|
|
118
|
+
|
|
119
|
+
expect(wrapper.find('.dm-avatar__badge').exists()).toBe(true)
|
|
120
|
+
expect(wrapper.find('.dm-avatar__badge--online').exists()).toBe(true)
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
it('supports different status types', () => {
|
|
124
|
+
const statuses = ['online', 'offline', 'away', 'busy']
|
|
125
|
+
|
|
126
|
+
statuses.forEach(status => {
|
|
127
|
+
const wrapper = createWrapper({ badge: true, status })
|
|
128
|
+
expect(wrapper.find(`.dm-avatar__badge--${status}`).exists()).toBe(true)
|
|
129
|
+
})
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
it('supports alt text for accessibility', () => {
|
|
133
|
+
const alt = 'User avatar'
|
|
134
|
+
const wrapper = createWrapper({ src: 'avatar.jpg', alt })
|
|
135
|
+
|
|
136
|
+
const img = wrapper.find('.dm-avatar__image')
|
|
137
|
+
expect(img.attributes('alt')).toBe(alt)
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('generates alt text from name when not provided', () => {
|
|
141
|
+
const name = 'John Doe'
|
|
142
|
+
const wrapper = createWrapper({ src: 'avatar.jpg', name })
|
|
143
|
+
|
|
144
|
+
const img = wrapper.find('.dm-avatar__image')
|
|
145
|
+
expect(img.attributes('alt')).toBe(`${name} avatar`)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('supports loading state', () => {
|
|
149
|
+
const wrapper = createWrapper({ loading: true })
|
|
150
|
+
expect(wrapper.find('.dm-avatar--loading').exists()).toBe(true)
|
|
151
|
+
})
|
|
152
|
+
})
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
2
|
-
import { mount } from '@vue/test-utils'
|
|
3
|
-
import DatametriaBadge from '../DatametriaBadge.vue'
|
|
4
|
-
|
|
5
|
-
describe('DatametriaBadge', () => {
|
|
6
|
-
it('renders with primary variant', () => {
|
|
7
|
-
const wrapper = mount(DatametriaBadge, {
|
|
8
|
-
props: { label: 'Test', variant: 'primary' }
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
expect(wrapper.classes()).toContain('dm-badge--primary')
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
it('validates invalid variant in development', () => {
|
|
15
|
-
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
16
|
-
const originalEnv = process.env.NODE_ENV
|
|
17
|
-
process.env.NODE_ENV = 'development'
|
|
18
|
-
|
|
19
|
-
mount(DatametriaBadge, {
|
|
20
|
-
props: { label: 'Test', variant: 'invalid' }
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
24
|
-
expect.stringContaining('[DatametriaBadge] Invalid variant "invalid"')
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
process.env.NODE_ENV = originalEnv
|
|
28
|
-
consoleSpy.mockRestore()
|
|
29
|
-
})
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest'
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import DatametriaBadge from '../DatametriaBadge.vue'
|
|
4
|
+
|
|
5
|
+
describe('DatametriaBadge', () => {
|
|
6
|
+
it('renders with primary variant', () => {
|
|
7
|
+
const wrapper = mount(DatametriaBadge, {
|
|
8
|
+
props: { label: 'Test', variant: 'primary' }
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
expect(wrapper.classes()).toContain('dm-badge--primary')
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
it('validates invalid variant in development', () => {
|
|
15
|
+
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
16
|
+
const originalEnv = process.env.NODE_ENV
|
|
17
|
+
process.env.NODE_ENV = 'development'
|
|
18
|
+
|
|
19
|
+
mount(DatametriaBadge, {
|
|
20
|
+
props: { label: 'Test', variant: 'invalid' }
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
24
|
+
expect.stringContaining('[DatametriaBadge] Invalid variant "invalid"')
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
process.env.NODE_ENV = originalEnv
|
|
28
|
+
consoleSpy.mockRestore()
|
|
29
|
+
})
|
|
30
30
|
})
|