@datametria/vue-components 2.3.1 → 2.4.0
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 +625 -594
- package/dist/index.es.js +1962 -1887
- package/dist/index.umd.js +6 -6
- package/dist/src/components/DatametriaForm.vue.d.ts +1 -1
- package/dist/src/components/DatametriaInput.vue.d.ts +9 -1
- package/dist/src/components/DatametriaSelect.vue.d.ts +10 -1
- package/dist/vue-components.css +1 -1
- package/package.json +103 -102
- package/src/components/DatametriaAlert.vue +151 -133
- package/src/components/DatametriaAutocomplete.vue +250 -229
- package/src/components/DatametriaAvatar.vue +256 -238
- package/src/components/DatametriaBadge.vue +101 -96
- package/src/components/DatametriaBreadcrumb.vue +132 -128
- package/src/components/DatametriaButton.vue +191 -173
- package/src/components/DatametriaCard.vue +84 -66
- package/src/components/DatametriaCheckbox.vue +197 -193
- package/src/components/DatametriaCheckboxGroup.vue +56 -38
- package/src/components/DatametriaChip.vue +159 -141
- package/src/components/DatametriaContainer.vue +70 -52
- package/src/components/DatametriaDataTable.vue +318 -300
- package/src/components/DatametriaDatePicker.vue +396 -378
- package/src/components/DatametriaDialog.vue +297 -293
- package/src/components/DatametriaDivider.vue +105 -98
- package/src/components/DatametriaDropdown.vue +356 -350
- package/src/components/DatametriaEmpty.vue +155 -151
- package/src/components/DatametriaFileUpload.vue +413 -395
- package/src/components/DatametriaFloatingBar.vue +144 -126
- package/src/components/DatametriaForm.vue +174 -156
- package/src/components/DatametriaFormItem.vue +183 -179
- package/src/components/DatametriaGrid.vue +55 -37
- package/src/components/DatametriaInput.vue +314 -263
- package/src/components/DatametriaMenu.vue +618 -600
- package/src/components/DatametriaModal.vue +147 -129
- package/src/components/DatametriaNavbar.vue +277 -223
- package/src/components/DatametriaPagination.vue +375 -371
- package/src/components/DatametriaPasswordInput.vue +444 -426
- package/src/components/DatametriaPopconfirm.vue +240 -234
- package/src/components/DatametriaProgress.vue +228 -224
- package/src/components/DatametriaRadio.vue +151 -147
- package/src/components/DatametriaRadioGroup.vue +55 -37
- package/src/components/DatametriaResult.vue +135 -131
- package/src/components/DatametriaSelect.vue +311 -211
- package/src/components/DatametriaSidebar.vue +294 -222
- package/src/components/DatametriaSkeleton.vue +257 -234
- package/src/components/DatametriaSlider.vue +409 -391
- package/src/components/DatametriaSortableTable.vue +820 -802
- package/src/components/DatametriaSpinner.vue +114 -110
- package/src/components/DatametriaSteps.vue +318 -312
- package/src/components/DatametriaSwitch.vue +146 -142
- package/src/components/DatametriaTabPane.vue +94 -76
- package/src/components/DatametriaTable.vue +118 -100
- package/src/components/DatametriaTabs.vue +315 -297
- package/src/components/DatametriaTextarea.vue +213 -195
- package/src/components/DatametriaTimePicker.vue +317 -299
- package/src/components/DatametriaToast.vue +176 -176
- package/src/components/DatametriaTooltip.vue +421 -400
- package/src/components/DatametriaTree.vue +126 -122
- package/src/components/DatametriaTreeNode.vue +176 -172
- package/src/components/DatametriaUpload.vue +379 -361
- package/src/components/__tests__/DatametriaAlert.test.js +35 -35
- package/src/components/__tests__/DatametriaAlert.test.ts +190 -190
- package/src/components/__tests__/DatametriaAvatar.test.ts +151 -151
- package/src/components/__tests__/DatametriaBadge.test.js +29 -29
- package/src/components/__tests__/DatametriaBadge.test.ts +167 -167
- package/src/components/__tests__/DatametriaBreadcrumb.test.ts +187 -0
- package/src/components/__tests__/DatametriaButton.test.js +30 -30
- package/src/components/__tests__/DatametriaButton.test.ts +283 -283
- package/src/components/__tests__/DatametriaCard.test.ts +201 -201
- package/src/components/__tests__/DatametriaCheckbox.test.ts +204 -0
- package/src/components/__tests__/DatametriaChip.test.js +38 -38
- package/src/components/__tests__/DatametriaContainer.test.ts +52 -52
- package/src/components/__tests__/DatametriaDialog.test.ts +338 -0
- package/src/components/__tests__/DatametriaDivider.test.ts +54 -54
- package/src/components/__tests__/DatametriaDropdown.test.ts +357 -0
- package/src/components/__tests__/DatametriaEmpty.test.ts +261 -0
- package/src/components/__tests__/DatametriaFileUpload.test.ts +290 -290
- package/src/components/__tests__/DatametriaFloatingBar.test.ts +137 -137
- package/src/components/__tests__/DatametriaForm.test.ts +96 -0
- package/src/components/__tests__/DatametriaFormItem.test.ts +58 -0
- package/src/components/__tests__/DatametriaGrid.test.ts +31 -31
- package/src/components/__tests__/DatametriaInput.test.ts +72 -72
- package/src/components/__tests__/DatametriaMenu.test.ts +366 -366
- package/src/components/__tests__/DatametriaModal.test.ts +86 -86
- package/src/components/__tests__/DatametriaNavbar.test.js +48 -48
- package/src/components/__tests__/DatametriaNavbar.test.ts +203 -203
- package/src/components/__tests__/DatametriaPasswordInput.test.js +305 -305
- package/src/components/__tests__/DatametriaRadio.test.ts +195 -0
- package/src/components/__tests__/DatametriaSelect.test.ts +77 -77
- package/src/components/__tests__/DatametriaSidebar.test.ts +169 -169
- package/src/components/__tests__/DatametriaSlider.test.ts +261 -261
- package/src/components/__tests__/DatametriaSortableTable.test.js +168 -168
- package/src/components/__tests__/DatametriaSpinner.test.ts +156 -156
- package/src/components/__tests__/DatametriaSteps.test.ts +211 -0
- package/src/components/__tests__/DatametriaSwitch.test.ts +129 -0
- package/src/components/__tests__/DatametriaTabPane.test.ts +205 -0
- package/src/components/__tests__/DatametriaTable.test.ts +97 -97
- package/src/components/__tests__/DatametriaTabs.test.ts +232 -232
- package/src/components/__tests__/DatametriaToast.test.js +48 -48
- package/src/components/__tests__/DatametriaToast.test.ts +99 -99
- package/src/components/__tests__/DatametriaTree.test.ts +376 -0
- package/src/components/__tests__/index.test.ts +48 -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/composables/useTheme.ts +5 -1
- package/src/index.ts +84 -84
- package/src/stories/Variants.stories.js +95 -95
- package/src/styles/design-tokens.css +623 -623
- package/src/theme/ThemeProvider.vue +96 -96
- package/src/theme/__tests__/ThemeProvider.test.ts +208 -208
- package/src/theme/__tests__/constants.test.ts +31 -31
- package/src/theme/__tests__/presets.test.ts +166 -166
- package/src/theme/__tests__/tokens.test.ts +155 -155
- package/src/theme/__tests__/types.test.ts +153 -153
- package/src/theme/__tests__/useTheme.test.ts +146 -146
- package/src/theme/constants.ts +14 -14
- package/src/theme/index.ts +12 -12
- package/src/theme/presets/datametria.ts +94 -94
- package/src/theme/presets/default.ts +94 -94
- package/src/theme/presets/index.ts +8 -8
- package/src/theme/tokens/colors.ts +28 -28
- package/src/theme/tokens/index.ts +47 -47
- package/src/theme/tokens/spacing.ts +21 -21
- package/src/theme/tokens/typography.ts +35 -35
- package/src/theme/types.ts +111 -111
- package/src/theme/useTheme.ts +28 -28
- package/src/types/index.ts +55 -55
|
@@ -1,305 +1,305 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
2
|
-
import { mount } from '@vue/test-utils'
|
|
3
|
-
import DatametriaPasswordInput from '../DatametriaPasswordInput.vue'
|
|
4
|
-
|
|
5
|
-
describe('DatametriaPasswordInput', () => {
|
|
6
|
-
it('renders correctly', () => {
|
|
7
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
8
|
-
props: {
|
|
9
|
-
label: 'Senha'
|
|
10
|
-
}
|
|
11
|
-
})
|
|
12
|
-
expect(wrapper.find('.datametria-password-input').exists()).toBe(true)
|
|
13
|
-
expect(wrapper.find('label').text()).toContain('Senha')
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
it('toggles password visibility', async () => {
|
|
17
|
-
const wrapper = mount(DatametriaPasswordInput)
|
|
18
|
-
const input = wrapper.find('input')
|
|
19
|
-
const toggleButton = wrapper.find('.datametria-password-input__toggle')
|
|
20
|
-
|
|
21
|
-
expect(input.attributes('type')).toBe('password')
|
|
22
|
-
|
|
23
|
-
await toggleButton.trigger('click')
|
|
24
|
-
expect(input.attributes('type')).toBe('text')
|
|
25
|
-
|
|
26
|
-
await toggleButton.trigger('click')
|
|
27
|
-
expect(input.attributes('type')).toBe('password')
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('validates password strength', async () => {
|
|
31
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
32
|
-
props: {
|
|
33
|
-
modelValue: '',
|
|
34
|
-
showStrength: true
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
// Weak password
|
|
39
|
-
await wrapper.setProps({ modelValue: 'abc' })
|
|
40
|
-
expect(wrapper.find('.datametria-password-input__strength-text--weak').exists()).toBe(true)
|
|
41
|
-
|
|
42
|
-
// Strong password
|
|
43
|
-
await wrapper.setProps({ modelValue: 'Abc123!@#' })
|
|
44
|
-
expect(wrapper.find('.datametria-password-input__strength-text--strong').exists()).toBe(true)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
it('shows requirements when focused', async () => {
|
|
48
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
49
|
-
props: {
|
|
50
|
-
showRequirements: true
|
|
51
|
-
}
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
const input = wrapper.find('input')
|
|
55
|
-
|
|
56
|
-
expect(wrapper.find('.datametria-password-input__requirements').exists()).toBe(false)
|
|
57
|
-
|
|
58
|
-
await input.trigger('focus')
|
|
59
|
-
expect(wrapper.find('.datametria-password-input__requirements').exists()).toBe(true)
|
|
60
|
-
|
|
61
|
-
await input.trigger('blur')
|
|
62
|
-
expect(wrapper.find('.datametria-password-input__requirements').exists()).toBe(false)
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
it('validates all requirements', async () => {
|
|
66
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
67
|
-
props: {
|
|
68
|
-
modelValue: 'Abc123!@#',
|
|
69
|
-
showRequirements: true
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
await wrapper.find('input').trigger('focus')
|
|
74
|
-
|
|
75
|
-
const requirements = wrapper.findAll('.datametria-password-input__requirements-list li')
|
|
76
|
-
expect(requirements).toHaveLength(5)
|
|
77
|
-
|
|
78
|
-
// All requirements should be valid
|
|
79
|
-
requirements.forEach(req => {
|
|
80
|
-
expect(req.classes()).toContain('valid')
|
|
81
|
-
})
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('emits update:modelValue on input', async () => {
|
|
85
|
-
const wrapper = mount(DatametriaPasswordInput)
|
|
86
|
-
const input = wrapper.find('input')
|
|
87
|
-
|
|
88
|
-
await input.setValue('test123')
|
|
89
|
-
expect(wrapper.emitted('update:modelValue')).toBeTruthy()
|
|
90
|
-
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual(['test123'])
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
it('emits strength-change event', async () => {
|
|
94
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
95
|
-
props: {
|
|
96
|
-
modelValue: ''
|
|
97
|
-
}
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
await wrapper.setProps({ modelValue: 'Abc123!@#' })
|
|
101
|
-
await wrapper.vm.$nextTick()
|
|
102
|
-
|
|
103
|
-
expect(wrapper.emitted('strength-change')).toBeTruthy()
|
|
104
|
-
expect(wrapper.emitted('strength-change')?.[0]?.[0]).toBe(100)
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
it('shows error message', () => {
|
|
108
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
109
|
-
props: {
|
|
110
|
-
errorMessage: 'Senha inválida'
|
|
111
|
-
}
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
expect(wrapper.find('.datametria-password-input__error').text()).toBe('Senha inválida')
|
|
115
|
-
expect(wrapper.find('input').classes()).toContain('datametria-password-input__field--error')
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
it('shows help text', () => {
|
|
119
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
120
|
-
props: {
|
|
121
|
-
helpText: 'Use uma senha forte'
|
|
122
|
-
}
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
expect(wrapper.find('.datametria-password-input__help').text()).toBe('Use uma senha forte')
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
it('marks required field', () => {
|
|
129
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
130
|
-
props: {
|
|
131
|
-
label: 'Senha',
|
|
132
|
-
required: true
|
|
133
|
-
}
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
expect(wrapper.find('.datametria-password-input__required').exists()).toBe(true)
|
|
137
|
-
expect(wrapper.find('input').attributes('required')).toBeDefined()
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
it('disables input when disabled prop is true', () => {
|
|
141
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
142
|
-
props: {
|
|
143
|
-
disabled: true
|
|
144
|
-
}
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
const input = wrapper.find('input')
|
|
148
|
-
expect(input.attributes('disabled')).toBeDefined()
|
|
149
|
-
expect(input.classes()).toContain('datametria-password-input__field--disabled')
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
it('sets correct autocomplete attribute', () => {
|
|
153
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
154
|
-
props: {
|
|
155
|
-
autocomplete: 'new-password'
|
|
156
|
-
}
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
expect(wrapper.find('input').attributes('autocomplete')).toBe('new-password')
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
it('has proper ARIA attributes', async () => {
|
|
163
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
164
|
-
props: {
|
|
165
|
-
errorMessage: 'Senha inválida',
|
|
166
|
-
showRequirements: true
|
|
167
|
-
}
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
const input = wrapper.find('input')
|
|
171
|
-
|
|
172
|
-
expect(input.attributes('aria-invalid')).toBe('true')
|
|
173
|
-
|
|
174
|
-
await input.trigger('focus')
|
|
175
|
-
expect(input.attributes('aria-describedby')).toBeTruthy()
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
it('toggle button has proper accessibility', () => {
|
|
179
|
-
const wrapper = mount(DatametriaPasswordInput)
|
|
180
|
-
const toggleButton = wrapper.find('.datametria-password-input__toggle')
|
|
181
|
-
|
|
182
|
-
expect(toggleButton.attributes('aria-label')).toBe('Mostrar senha')
|
|
183
|
-
expect(toggleButton.attributes('type')).toBe('button')
|
|
184
|
-
expect(toggleButton.attributes('tabindex')).toBe('-1')
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
describe('CSS Variables Integration', () => {
|
|
188
|
-
it('uses semantic color tokens for strength indicators', async () => {
|
|
189
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
190
|
-
props: {
|
|
191
|
-
modelValue: 'Abc123!@#',
|
|
192
|
-
showStrength: true
|
|
193
|
-
}
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
expect(wrapper.find('.datametria-password-input__strength-fill--strong').exists()).toBe(true)
|
|
197
|
-
expect(wrapper.find('.datametria-password-input__strength-text--strong').exists()).toBe(true)
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
it('uses error token for error states', () => {
|
|
201
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
202
|
-
props: {
|
|
203
|
-
errorMessage: 'Error'
|
|
204
|
-
}
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
expect(wrapper.find('.datametria-password-input__field--error').exists()).toBe(true)
|
|
208
|
-
expect(wrapper.find('.datametria-password-input__error').exists()).toBe(true)
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
it('uses warning token for caps lock warning', async () => {
|
|
212
|
-
const wrapper = mount(DatametriaPasswordInput)
|
|
213
|
-
const input = wrapper.find('input')
|
|
214
|
-
|
|
215
|
-
const event = new KeyboardEvent('keyup', { key: 'A' })
|
|
216
|
-
Object.defineProperty(event, 'getModifierState', {
|
|
217
|
-
value: vi.fn(() => true)
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
await input.element.dispatchEvent(event)
|
|
221
|
-
await wrapper.vm.$nextTick()
|
|
222
|
-
|
|
223
|
-
expect(wrapper.find('.datametria-password-input__warning').exists()).toBe(true)
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
it('uses success token for valid requirements', async () => {
|
|
227
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
228
|
-
props: {
|
|
229
|
-
modelValue: 'Abc123!@#',
|
|
230
|
-
showRequirements: true
|
|
231
|
-
}
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
await wrapper.find('input').trigger('focus')
|
|
235
|
-
const validItems = wrapper.findAll('.datametria-password-input__requirements-list li.valid')
|
|
236
|
-
expect(validItems.length).toBe(5)
|
|
237
|
-
})
|
|
238
|
-
|
|
239
|
-
it('uses spacing tokens consistently', () => {
|
|
240
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
241
|
-
props: {
|
|
242
|
-
label: 'Password',
|
|
243
|
-
showRequirements: true
|
|
244
|
-
}
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
expect(wrapper.find('.datametria-password-input').exists()).toBe(true)
|
|
248
|
-
expect(wrapper.find('.datametria-password-input__field').exists()).toBe(true)
|
|
249
|
-
})
|
|
250
|
-
|
|
251
|
-
it('uses typography tokens for text elements', () => {
|
|
252
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
253
|
-
props: {
|
|
254
|
-
label: 'Password',
|
|
255
|
-
helpText: 'Help text'
|
|
256
|
-
}
|
|
257
|
-
})
|
|
258
|
-
|
|
259
|
-
expect(wrapper.find('.datametria-password-input__label').exists()).toBe(true)
|
|
260
|
-
expect(wrapper.find('.datametria-password-input__help').exists()).toBe(true)
|
|
261
|
-
})
|
|
262
|
-
|
|
263
|
-
it('uses transition tokens for animations', async () => {
|
|
264
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
265
|
-
props: {
|
|
266
|
-
modelValue: '',
|
|
267
|
-
showStrength: true
|
|
268
|
-
}
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
await wrapper.setProps({ modelValue: 'test' })
|
|
272
|
-
expect(wrapper.find('.datametria-password-input__strength-fill').exists()).toBe(true)
|
|
273
|
-
})
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
describe('Backward Compatibility', () => {
|
|
277
|
-
it('works without ThemeProvider', () => {
|
|
278
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
279
|
-
props: {
|
|
280
|
-
label: 'Password',
|
|
281
|
-
modelValue: 'Abc123!@#',
|
|
282
|
-
showStrength: true,
|
|
283
|
-
showRequirements: true
|
|
284
|
-
}
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
expect(wrapper.find('.datametria-password-input').exists()).toBe(true)
|
|
288
|
-
expect(wrapper.find('.datametria-password-input__strength').exists()).toBe(true)
|
|
289
|
-
})
|
|
290
|
-
|
|
291
|
-
it('maintains original visual appearance with fallback values', async () => {
|
|
292
|
-
const wrapper = mount(DatametriaPasswordInput, {
|
|
293
|
-
props: {
|
|
294
|
-
modelValue: 'weak',
|
|
295
|
-
showStrength: true
|
|
296
|
-
}
|
|
297
|
-
})
|
|
298
|
-
|
|
299
|
-
expect(wrapper.find('.datametria-password-input__strength-fill--weak').exists()).toBe(true)
|
|
300
|
-
|
|
301
|
-
await wrapper.setProps({ modelValue: 'Abc123!@#' })
|
|
302
|
-
expect(wrapper.find('.datametria-password-input__strength-fill--strong').exists()).toBe(true)
|
|
303
|
-
})
|
|
304
|
-
})
|
|
305
|
-
})
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest'
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import DatametriaPasswordInput from '../DatametriaPasswordInput.vue'
|
|
4
|
+
|
|
5
|
+
describe('DatametriaPasswordInput', () => {
|
|
6
|
+
it('renders correctly', () => {
|
|
7
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
8
|
+
props: {
|
|
9
|
+
label: 'Senha'
|
|
10
|
+
}
|
|
11
|
+
})
|
|
12
|
+
expect(wrapper.find('.datametria-password-input').exists()).toBe(true)
|
|
13
|
+
expect(wrapper.find('label').text()).toContain('Senha')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('toggles password visibility', async () => {
|
|
17
|
+
const wrapper = mount(DatametriaPasswordInput)
|
|
18
|
+
const input = wrapper.find('input')
|
|
19
|
+
const toggleButton = wrapper.find('.datametria-password-input__toggle')
|
|
20
|
+
|
|
21
|
+
expect(input.attributes('type')).toBe('password')
|
|
22
|
+
|
|
23
|
+
await toggleButton.trigger('click')
|
|
24
|
+
expect(input.attributes('type')).toBe('text')
|
|
25
|
+
|
|
26
|
+
await toggleButton.trigger('click')
|
|
27
|
+
expect(input.attributes('type')).toBe('password')
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('validates password strength', async () => {
|
|
31
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
32
|
+
props: {
|
|
33
|
+
modelValue: '',
|
|
34
|
+
showStrength: true
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// Weak password
|
|
39
|
+
await wrapper.setProps({ modelValue: 'abc' })
|
|
40
|
+
expect(wrapper.find('.datametria-password-input__strength-text--weak').exists()).toBe(true)
|
|
41
|
+
|
|
42
|
+
// Strong password
|
|
43
|
+
await wrapper.setProps({ modelValue: 'Abc123!@#' })
|
|
44
|
+
expect(wrapper.find('.datametria-password-input__strength-text--strong').exists()).toBe(true)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('shows requirements when focused', async () => {
|
|
48
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
49
|
+
props: {
|
|
50
|
+
showRequirements: true
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
const input = wrapper.find('input')
|
|
55
|
+
|
|
56
|
+
expect(wrapper.find('.datametria-password-input__requirements').exists()).toBe(false)
|
|
57
|
+
|
|
58
|
+
await input.trigger('focus')
|
|
59
|
+
expect(wrapper.find('.datametria-password-input__requirements').exists()).toBe(true)
|
|
60
|
+
|
|
61
|
+
await input.trigger('blur')
|
|
62
|
+
expect(wrapper.find('.datametria-password-input__requirements').exists()).toBe(false)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('validates all requirements', async () => {
|
|
66
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
67
|
+
props: {
|
|
68
|
+
modelValue: 'Abc123!@#',
|
|
69
|
+
showRequirements: true
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
await wrapper.find('input').trigger('focus')
|
|
74
|
+
|
|
75
|
+
const requirements = wrapper.findAll('.datametria-password-input__requirements-list li')
|
|
76
|
+
expect(requirements).toHaveLength(5)
|
|
77
|
+
|
|
78
|
+
// All requirements should be valid
|
|
79
|
+
requirements.forEach(req => {
|
|
80
|
+
expect(req.classes()).toContain('valid')
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('emits update:modelValue on input', async () => {
|
|
85
|
+
const wrapper = mount(DatametriaPasswordInput)
|
|
86
|
+
const input = wrapper.find('input')
|
|
87
|
+
|
|
88
|
+
await input.setValue('test123')
|
|
89
|
+
expect(wrapper.emitted('update:modelValue')).toBeTruthy()
|
|
90
|
+
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual(['test123'])
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('emits strength-change event', async () => {
|
|
94
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
95
|
+
props: {
|
|
96
|
+
modelValue: ''
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
await wrapper.setProps({ modelValue: 'Abc123!@#' })
|
|
101
|
+
await wrapper.vm.$nextTick()
|
|
102
|
+
|
|
103
|
+
expect(wrapper.emitted('strength-change')).toBeTruthy()
|
|
104
|
+
expect(wrapper.emitted('strength-change')?.[0]?.[0]).toBe(100)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('shows error message', () => {
|
|
108
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
109
|
+
props: {
|
|
110
|
+
errorMessage: 'Senha inválida'
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
expect(wrapper.find('.datametria-password-input__error').text()).toBe('Senha inválida')
|
|
115
|
+
expect(wrapper.find('input').classes()).toContain('datametria-password-input__field--error')
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('shows help text', () => {
|
|
119
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
120
|
+
props: {
|
|
121
|
+
helpText: 'Use uma senha forte'
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
expect(wrapper.find('.datametria-password-input__help').text()).toBe('Use uma senha forte')
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('marks required field', () => {
|
|
129
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
130
|
+
props: {
|
|
131
|
+
label: 'Senha',
|
|
132
|
+
required: true
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
expect(wrapper.find('.datametria-password-input__required').exists()).toBe(true)
|
|
137
|
+
expect(wrapper.find('input').attributes('required')).toBeDefined()
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('disables input when disabled prop is true', () => {
|
|
141
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
142
|
+
props: {
|
|
143
|
+
disabled: true
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
const input = wrapper.find('input')
|
|
148
|
+
expect(input.attributes('disabled')).toBeDefined()
|
|
149
|
+
expect(input.classes()).toContain('datametria-password-input__field--disabled')
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
it('sets correct autocomplete attribute', () => {
|
|
153
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
154
|
+
props: {
|
|
155
|
+
autocomplete: 'new-password'
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
expect(wrapper.find('input').attributes('autocomplete')).toBe('new-password')
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('has proper ARIA attributes', async () => {
|
|
163
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
164
|
+
props: {
|
|
165
|
+
errorMessage: 'Senha inválida',
|
|
166
|
+
showRequirements: true
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
const input = wrapper.find('input')
|
|
171
|
+
|
|
172
|
+
expect(input.attributes('aria-invalid')).toBe('true')
|
|
173
|
+
|
|
174
|
+
await input.trigger('focus')
|
|
175
|
+
expect(input.attributes('aria-describedby')).toBeTruthy()
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
it('toggle button has proper accessibility', () => {
|
|
179
|
+
const wrapper = mount(DatametriaPasswordInput)
|
|
180
|
+
const toggleButton = wrapper.find('.datametria-password-input__toggle')
|
|
181
|
+
|
|
182
|
+
expect(toggleButton.attributes('aria-label')).toBe('Mostrar senha')
|
|
183
|
+
expect(toggleButton.attributes('type')).toBe('button')
|
|
184
|
+
expect(toggleButton.attributes('tabindex')).toBe('-1')
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
describe('CSS Variables Integration', () => {
|
|
188
|
+
it('uses semantic color tokens for strength indicators', async () => {
|
|
189
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
190
|
+
props: {
|
|
191
|
+
modelValue: 'Abc123!@#',
|
|
192
|
+
showStrength: true
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
expect(wrapper.find('.datametria-password-input__strength-fill--strong').exists()).toBe(true)
|
|
197
|
+
expect(wrapper.find('.datametria-password-input__strength-text--strong').exists()).toBe(true)
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
it('uses error token for error states', () => {
|
|
201
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
202
|
+
props: {
|
|
203
|
+
errorMessage: 'Error'
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
expect(wrapper.find('.datametria-password-input__field--error').exists()).toBe(true)
|
|
208
|
+
expect(wrapper.find('.datametria-password-input__error').exists()).toBe(true)
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
it('uses warning token for caps lock warning', async () => {
|
|
212
|
+
const wrapper = mount(DatametriaPasswordInput)
|
|
213
|
+
const input = wrapper.find('input')
|
|
214
|
+
|
|
215
|
+
const event = new KeyboardEvent('keyup', { key: 'A' })
|
|
216
|
+
Object.defineProperty(event, 'getModifierState', {
|
|
217
|
+
value: vi.fn(() => true)
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
await input.element.dispatchEvent(event)
|
|
221
|
+
await wrapper.vm.$nextTick()
|
|
222
|
+
|
|
223
|
+
expect(wrapper.find('.datametria-password-input__warning').exists()).toBe(true)
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
it('uses success token for valid requirements', async () => {
|
|
227
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
228
|
+
props: {
|
|
229
|
+
modelValue: 'Abc123!@#',
|
|
230
|
+
showRequirements: true
|
|
231
|
+
}
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
await wrapper.find('input').trigger('focus')
|
|
235
|
+
const validItems = wrapper.findAll('.datametria-password-input__requirements-list li.valid')
|
|
236
|
+
expect(validItems.length).toBe(5)
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
it('uses spacing tokens consistently', () => {
|
|
240
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
241
|
+
props: {
|
|
242
|
+
label: 'Password',
|
|
243
|
+
showRequirements: true
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
expect(wrapper.find('.datametria-password-input').exists()).toBe(true)
|
|
248
|
+
expect(wrapper.find('.datametria-password-input__field').exists()).toBe(true)
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
it('uses typography tokens for text elements', () => {
|
|
252
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
253
|
+
props: {
|
|
254
|
+
label: 'Password',
|
|
255
|
+
helpText: 'Help text'
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
expect(wrapper.find('.datametria-password-input__label').exists()).toBe(true)
|
|
260
|
+
expect(wrapper.find('.datametria-password-input__help').exists()).toBe(true)
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
it('uses transition tokens for animations', async () => {
|
|
264
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
265
|
+
props: {
|
|
266
|
+
modelValue: '',
|
|
267
|
+
showStrength: true
|
|
268
|
+
}
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
await wrapper.setProps({ modelValue: 'test' })
|
|
272
|
+
expect(wrapper.find('.datametria-password-input__strength-fill').exists()).toBe(true)
|
|
273
|
+
})
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
describe('Backward Compatibility', () => {
|
|
277
|
+
it('works without ThemeProvider', () => {
|
|
278
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
279
|
+
props: {
|
|
280
|
+
label: 'Password',
|
|
281
|
+
modelValue: 'Abc123!@#',
|
|
282
|
+
showStrength: true,
|
|
283
|
+
showRequirements: true
|
|
284
|
+
}
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
expect(wrapper.find('.datametria-password-input').exists()).toBe(true)
|
|
288
|
+
expect(wrapper.find('.datametria-password-input__strength').exists()).toBe(true)
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
it('maintains original visual appearance with fallback values', async () => {
|
|
292
|
+
const wrapper = mount(DatametriaPasswordInput, {
|
|
293
|
+
props: {
|
|
294
|
+
modelValue: 'weak',
|
|
295
|
+
showStrength: true
|
|
296
|
+
}
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
expect(wrapper.find('.datametria-password-input__strength-fill--weak').exists()).toBe(true)
|
|
300
|
+
|
|
301
|
+
await wrapper.setProps({ modelValue: 'Abc123!@#' })
|
|
302
|
+
expect(wrapper.find('.datametria-password-input__strength-fill--strong').exists()).toBe(true)
|
|
303
|
+
})
|
|
304
|
+
})
|
|
305
|
+
})
|