@datametria/vue-components 2.3.0 → 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 -105
- 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,291 +1,291 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
2
|
-
import { mount } from '@vue/test-utils'
|
|
3
|
-
import DatametriaFileUpload from '../DatametriaFileUpload.vue'
|
|
4
|
-
import { datametriaTheme } from '../../theme/presets'
|
|
5
|
-
import { THEME_INJECTION_KEY } from '../../theme/constants'
|
|
6
|
-
|
|
7
|
-
const createWrapper = (props = {}, themeProps = {}) => {
|
|
8
|
-
return mount(DatametriaFileUpload, {
|
|
9
|
-
props,
|
|
10
|
-
global: {
|
|
11
|
-
plugins: [{
|
|
12
|
-
install(app) {
|
|
13
|
-
app.provide(THEME_INJECTION_KEY, datametriaTheme)
|
|
14
|
-
}
|
|
15
|
-
}]
|
|
16
|
-
}
|
|
17
|
-
})
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Mock File API
|
|
21
|
-
const createMockFile = (name: string, size: number, type: string) => {
|
|
22
|
-
const file = new File([''], name, { type })
|
|
23
|
-
Object.defineProperty(file, 'size', { value: size })
|
|
24
|
-
return file
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
describe('DatametriaFileUpload', () => {
|
|
28
|
-
beforeEach(() => {
|
|
29
|
-
vi.clearAllMocks()
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
it('renders correctly', () => {
|
|
33
|
-
const wrapper = createWrapper()
|
|
34
|
-
expect(wrapper.find('.dm-file-upload').exists()).toBe(true)
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
it('applies theme colors correctly', () => {
|
|
38
|
-
const wrapper = createWrapper()
|
|
39
|
-
expect(wrapper.find('.dm-file-upload').exists()).toBe(true)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('displays upload area', () => {
|
|
43
|
-
const wrapper = createWrapper()
|
|
44
|
-
expect(wrapper.find('.dm-file-upload__area').exists()).toBe(true)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
it('shows upload text and icon', () => {
|
|
48
|
-
const wrapper = createWrapper()
|
|
49
|
-
expect(wrapper.find('.dm-file-upload__icon').exists()).toBe(true)
|
|
50
|
-
expect(wrapper.find('.dm-file-upload__text').exists()).toBe(true)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
it('handles file selection via input', async () => {
|
|
54
|
-
const wrapper = createWrapper()
|
|
55
|
-
const input = wrapper.find('.dm-file-upload__input')
|
|
56
|
-
const file = createMockFile('test.txt', 1024, 'text/plain')
|
|
57
|
-
|
|
58
|
-
Object.defineProperty(input.element, 'files', {
|
|
59
|
-
value: [file],
|
|
60
|
-
writable: false
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
await input.trigger('change')
|
|
64
|
-
|
|
65
|
-
const fileUpload = wrapper.findComponent(DatametriaFileUpload)
|
|
66
|
-
expect(fileUpload.emitted('update:modelValue')).toBeTruthy()
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
it('handles drag and drop', async () => {
|
|
70
|
-
const wrapper = createWrapper()
|
|
71
|
-
const dropArea = wrapper.find('.dm-file-upload__area')
|
|
72
|
-
const file = createMockFile('test.txt', 1024, 'text/plain')
|
|
73
|
-
|
|
74
|
-
const mockDataTransfer = {
|
|
75
|
-
files: [file]
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
await dropArea.trigger('drop', {
|
|
79
|
-
dataTransfer: mockDataTransfer
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
const fileUpload = wrapper.findComponent(DatametriaFileUpload)
|
|
83
|
-
expect(fileUpload.emitted('update:modelValue')).toBeTruthy()
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
it('shows drag over state', async () => {
|
|
87
|
-
const wrapper = createWrapper()
|
|
88
|
-
const dropArea = wrapper.find('.dm-file-upload__area')
|
|
89
|
-
|
|
90
|
-
await dropArea.trigger('dragenter')
|
|
91
|
-
await wrapper.vm.$nextTick()
|
|
92
|
-
expect(wrapper.find('.dm-file-upload__area--dragover').exists()).toBe(true)
|
|
93
|
-
|
|
94
|
-
await dropArea.trigger('dragleave', {
|
|
95
|
-
relatedTarget: document.body
|
|
96
|
-
})
|
|
97
|
-
await wrapper.vm.$nextTick()
|
|
98
|
-
expect(wrapper.find('.dm-file-upload__area--dragover').exists()).toBe(false)
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
it('supports multiple file selection', async () => {
|
|
102
|
-
const wrapper = createWrapper({ multiple: true })
|
|
103
|
-
const input = wrapper.find('.dm-file-upload__input')
|
|
104
|
-
|
|
105
|
-
expect(input.attributes('multiple')).toBeDefined()
|
|
106
|
-
|
|
107
|
-
const files = [
|
|
108
|
-
createMockFile('test1.txt', 1024, 'text/plain'),
|
|
109
|
-
createMockFile('test2.txt', 2048, 'text/plain')
|
|
110
|
-
]
|
|
111
|
-
|
|
112
|
-
Object.defineProperty(input.element, 'files', {
|
|
113
|
-
value: files,
|
|
114
|
-
writable: false
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
await input.trigger('change')
|
|
118
|
-
|
|
119
|
-
const fileUpload = wrapper.findComponent(DatametriaFileUpload)
|
|
120
|
-
expect(fileUpload.emitted('update:modelValue')).toBeTruthy()
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
it('validates file types', async () => {
|
|
124
|
-
const wrapper = createWrapper({ accept: '.txt,.pdf' })
|
|
125
|
-
const input = wrapper.find('.dm-file-upload__input')
|
|
126
|
-
|
|
127
|
-
expect(input.attributes('accept')).toBe('.txt,.pdf')
|
|
128
|
-
|
|
129
|
-
const invalidFile = createMockFile('test.jpg', 1024, 'image/jpeg')
|
|
130
|
-
Object.defineProperty(input.element, 'files', {
|
|
131
|
-
value: [invalidFile],
|
|
132
|
-
writable: false
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
await input.trigger('change')
|
|
136
|
-
await wrapper.vm.$nextTick()
|
|
137
|
-
|
|
138
|
-
expect(wrapper.text()).toContain('Invalid file type')
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
it('validates file size', async () => {
|
|
142
|
-
const wrapper = createWrapper({ maxSize: 1024 }) // 1KB
|
|
143
|
-
const input = wrapper.find('.dm-file-upload__input')
|
|
144
|
-
|
|
145
|
-
const largeFile = createMockFile('large.txt', 2048, 'text/plain') // 2KB
|
|
146
|
-
Object.defineProperty(input.element, 'files', {
|
|
147
|
-
value: [largeFile],
|
|
148
|
-
writable: false
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
await input.trigger('change')
|
|
152
|
-
await wrapper.vm.$nextTick()
|
|
153
|
-
|
|
154
|
-
expect(wrapper.text()).toContain('too large')
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
it('validates maximum number of files', async () => {
|
|
158
|
-
const wrapper = createWrapper({ multiple: true, maxFiles: 2 })
|
|
159
|
-
const input = wrapper.find('.dm-file-upload__input')
|
|
160
|
-
|
|
161
|
-
const files = [
|
|
162
|
-
createMockFile('test1.txt', 1024, 'text/plain'),
|
|
163
|
-
createMockFile('test2.txt', 1024, 'text/plain'),
|
|
164
|
-
createMockFile('test3.txt', 1024, 'text/plain')
|
|
165
|
-
]
|
|
166
|
-
|
|
167
|
-
Object.defineProperty(input.element, 'files', {
|
|
168
|
-
value: files,
|
|
169
|
-
writable: false
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
await input.trigger('change')
|
|
173
|
-
await wrapper.vm.$nextTick()
|
|
174
|
-
|
|
175
|
-
expect(wrapper.text()).toContain('Maximum 2 files')
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
it('shows file list when files are selected', async () => {
|
|
179
|
-
const wrapper = createWrapper({ multiple: true })
|
|
180
|
-
const input = wrapper.find('.dm-file-upload__input')
|
|
181
|
-
|
|
182
|
-
const files = [
|
|
183
|
-
createMockFile('test1.txt', 1024, 'text/plain'),
|
|
184
|
-
createMockFile('test2.txt', 2048, 'text/plain')
|
|
185
|
-
]
|
|
186
|
-
|
|
187
|
-
Object.defineProperty(input.element, 'files', {
|
|
188
|
-
value: files,
|
|
189
|
-
writable: false
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
await input.trigger('change')
|
|
193
|
-
|
|
194
|
-
expect(wrapper.find('.dm-file-upload__files').exists()).toBe(true)
|
|
195
|
-
expect(wrapper.findAll('.dm-file-upload__file')).toHaveLength(2)
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
it('allows file removal', async () => {
|
|
199
|
-
const wrapper = createWrapper({ multiple: true })
|
|
200
|
-
const input = wrapper.find('.dm-file-upload__input')
|
|
201
|
-
|
|
202
|
-
const files = [
|
|
203
|
-
createMockFile('test1.txt', 1024, 'text/plain'),
|
|
204
|
-
createMockFile('test2.txt', 2048, 'text/plain')
|
|
205
|
-
]
|
|
206
|
-
|
|
207
|
-
Object.defineProperty(input.element, 'files', {
|
|
208
|
-
value: files,
|
|
209
|
-
writable: false
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
await input.trigger('change')
|
|
213
|
-
|
|
214
|
-
const removeButton = wrapper.find('.dm-file-upload__remove')
|
|
215
|
-
await removeButton.trigger('click')
|
|
216
|
-
|
|
217
|
-
const fileUpload = wrapper.findComponent(DatametriaFileUpload)
|
|
218
|
-
expect(fileUpload.emitted('update:modelValue')).toBeTruthy()
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
it('supports disabled state', () => {
|
|
222
|
-
const wrapper = createWrapper({ disabled: true })
|
|
223
|
-
const input = wrapper.find('.dm-file-upload__input')
|
|
224
|
-
|
|
225
|
-
expect(input.attributes('disabled')).toBeDefined()
|
|
226
|
-
expect(wrapper.find('.dm-file-upload--disabled').exists()).toBe(true)
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
it('shows loading state during upload', () => {
|
|
230
|
-
const wrapper = createWrapper({ loading: true })
|
|
231
|
-
expect(wrapper.find('.dm-file-upload--loading').exists()).toBe(true)
|
|
232
|
-
expect(wrapper.find('.dm-file-upload__spinner').exists()).toBe(true)
|
|
233
|
-
})
|
|
234
|
-
|
|
235
|
-
it('shows upload progress', () => {
|
|
236
|
-
const wrapper = createWrapper({ progress: 50 })
|
|
237
|
-
const progressBar = wrapper.find('.dm-file-upload__progress-bar')
|
|
238
|
-
|
|
239
|
-
expect(progressBar.exists()).toBe(true)
|
|
240
|
-
expect(progressBar.attributes('style')).toContain('width: 50%')
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
it('supports custom upload text', () => {
|
|
244
|
-
const customText = 'Drop your files here'
|
|
245
|
-
const wrapper = createWrapper({ uploadText: customText })
|
|
246
|
-
|
|
247
|
-
expect(wrapper.find('.dm-file-upload__text').text()).toContain(customText)
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
it('supports custom error messages', () => {
|
|
251
|
-
const errorMessage = 'Upload failed'
|
|
252
|
-
const wrapper = createWrapper({ error: errorMessage })
|
|
253
|
-
|
|
254
|
-
expect(wrapper.find('.dm-file-upload__error').text()).toBe(errorMessage)
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
it('emits file-added event', async () => {
|
|
258
|
-
const wrapper = createWrapper()
|
|
259
|
-
const input = wrapper.find('.dm-file-upload__input')
|
|
260
|
-
const file = createMockFile('test.txt', 1024, 'text/plain')
|
|
261
|
-
|
|
262
|
-
Object.defineProperty(input.element, 'files', {
|
|
263
|
-
value: [file],
|
|
264
|
-
writable: false
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
await input.trigger('change')
|
|
268
|
-
|
|
269
|
-
const fileUpload = wrapper.findComponent(DatametriaFileUpload)
|
|
270
|
-
expect(fileUpload.emitted('file-added')).toBeTruthy()
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
it('emits file-removed event', async () => {
|
|
274
|
-
const wrapper = createWrapper({ multiple: true })
|
|
275
|
-
const input = wrapper.find('.dm-file-upload__input')
|
|
276
|
-
|
|
277
|
-
const files = [createMockFile('test.txt', 1024, 'text/plain')]
|
|
278
|
-
Object.defineProperty(input.element, 'files', {
|
|
279
|
-
value: files,
|
|
280
|
-
writable: false
|
|
281
|
-
})
|
|
282
|
-
|
|
283
|
-
await input.trigger('change')
|
|
284
|
-
|
|
285
|
-
const removeButton = wrapper.find('.dm-file-upload__remove')
|
|
286
|
-
await removeButton.trigger('click')
|
|
287
|
-
|
|
288
|
-
const fileUpload = wrapper.findComponent(DatametriaFileUpload)
|
|
289
|
-
expect(fileUpload.emitted('file-removed')).toBeTruthy()
|
|
290
|
-
})
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import DatametriaFileUpload from '../DatametriaFileUpload.vue'
|
|
4
|
+
import { datametriaTheme } from '../../theme/presets'
|
|
5
|
+
import { THEME_INJECTION_KEY } from '../../theme/constants'
|
|
6
|
+
|
|
7
|
+
const createWrapper = (props = {}, themeProps = {}) => {
|
|
8
|
+
return mount(DatametriaFileUpload, {
|
|
9
|
+
props,
|
|
10
|
+
global: {
|
|
11
|
+
plugins: [{
|
|
12
|
+
install(app) {
|
|
13
|
+
app.provide(THEME_INJECTION_KEY, datametriaTheme)
|
|
14
|
+
}
|
|
15
|
+
}]
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Mock File API
|
|
21
|
+
const createMockFile = (name: string, size: number, type: string) => {
|
|
22
|
+
const file = new File([''], name, { type })
|
|
23
|
+
Object.defineProperty(file, 'size', { value: size })
|
|
24
|
+
return file
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe('DatametriaFileUpload', () => {
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
vi.clearAllMocks()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('renders correctly', () => {
|
|
33
|
+
const wrapper = createWrapper()
|
|
34
|
+
expect(wrapper.find('.dm-file-upload').exists()).toBe(true)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('applies theme colors correctly', () => {
|
|
38
|
+
const wrapper = createWrapper()
|
|
39
|
+
expect(wrapper.find('.dm-file-upload').exists()).toBe(true)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('displays upload area', () => {
|
|
43
|
+
const wrapper = createWrapper()
|
|
44
|
+
expect(wrapper.find('.dm-file-upload__area').exists()).toBe(true)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('shows upload text and icon', () => {
|
|
48
|
+
const wrapper = createWrapper()
|
|
49
|
+
expect(wrapper.find('.dm-file-upload__icon').exists()).toBe(true)
|
|
50
|
+
expect(wrapper.find('.dm-file-upload__text').exists()).toBe(true)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('handles file selection via input', async () => {
|
|
54
|
+
const wrapper = createWrapper()
|
|
55
|
+
const input = wrapper.find('.dm-file-upload__input')
|
|
56
|
+
const file = createMockFile('test.txt', 1024, 'text/plain')
|
|
57
|
+
|
|
58
|
+
Object.defineProperty(input.element, 'files', {
|
|
59
|
+
value: [file],
|
|
60
|
+
writable: false
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
await input.trigger('change')
|
|
64
|
+
|
|
65
|
+
const fileUpload = wrapper.findComponent(DatametriaFileUpload)
|
|
66
|
+
expect(fileUpload.emitted('update:modelValue')).toBeTruthy()
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('handles drag and drop', async () => {
|
|
70
|
+
const wrapper = createWrapper()
|
|
71
|
+
const dropArea = wrapper.find('.dm-file-upload__area')
|
|
72
|
+
const file = createMockFile('test.txt', 1024, 'text/plain')
|
|
73
|
+
|
|
74
|
+
const mockDataTransfer = {
|
|
75
|
+
files: [file]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
await dropArea.trigger('drop', {
|
|
79
|
+
dataTransfer: mockDataTransfer
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
const fileUpload = wrapper.findComponent(DatametriaFileUpload)
|
|
83
|
+
expect(fileUpload.emitted('update:modelValue')).toBeTruthy()
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('shows drag over state', async () => {
|
|
87
|
+
const wrapper = createWrapper()
|
|
88
|
+
const dropArea = wrapper.find('.dm-file-upload__area')
|
|
89
|
+
|
|
90
|
+
await dropArea.trigger('dragenter')
|
|
91
|
+
await wrapper.vm.$nextTick()
|
|
92
|
+
expect(wrapper.find('.dm-file-upload__area--dragover').exists()).toBe(true)
|
|
93
|
+
|
|
94
|
+
await dropArea.trigger('dragleave', {
|
|
95
|
+
relatedTarget: document.body
|
|
96
|
+
})
|
|
97
|
+
await wrapper.vm.$nextTick()
|
|
98
|
+
expect(wrapper.find('.dm-file-upload__area--dragover').exists()).toBe(false)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('supports multiple file selection', async () => {
|
|
102
|
+
const wrapper = createWrapper({ multiple: true })
|
|
103
|
+
const input = wrapper.find('.dm-file-upload__input')
|
|
104
|
+
|
|
105
|
+
expect(input.attributes('multiple')).toBeDefined()
|
|
106
|
+
|
|
107
|
+
const files = [
|
|
108
|
+
createMockFile('test1.txt', 1024, 'text/plain'),
|
|
109
|
+
createMockFile('test2.txt', 2048, 'text/plain')
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
Object.defineProperty(input.element, 'files', {
|
|
113
|
+
value: files,
|
|
114
|
+
writable: false
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
await input.trigger('change')
|
|
118
|
+
|
|
119
|
+
const fileUpload = wrapper.findComponent(DatametriaFileUpload)
|
|
120
|
+
expect(fileUpload.emitted('update:modelValue')).toBeTruthy()
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
it('validates file types', async () => {
|
|
124
|
+
const wrapper = createWrapper({ accept: '.txt,.pdf' })
|
|
125
|
+
const input = wrapper.find('.dm-file-upload__input')
|
|
126
|
+
|
|
127
|
+
expect(input.attributes('accept')).toBe('.txt,.pdf')
|
|
128
|
+
|
|
129
|
+
const invalidFile = createMockFile('test.jpg', 1024, 'image/jpeg')
|
|
130
|
+
Object.defineProperty(input.element, 'files', {
|
|
131
|
+
value: [invalidFile],
|
|
132
|
+
writable: false
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
await input.trigger('change')
|
|
136
|
+
await wrapper.vm.$nextTick()
|
|
137
|
+
|
|
138
|
+
expect(wrapper.text()).toContain('Invalid file type')
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it('validates file size', async () => {
|
|
142
|
+
const wrapper = createWrapper({ maxSize: 1024 }) // 1KB
|
|
143
|
+
const input = wrapper.find('.dm-file-upload__input')
|
|
144
|
+
|
|
145
|
+
const largeFile = createMockFile('large.txt', 2048, 'text/plain') // 2KB
|
|
146
|
+
Object.defineProperty(input.element, 'files', {
|
|
147
|
+
value: [largeFile],
|
|
148
|
+
writable: false
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
await input.trigger('change')
|
|
152
|
+
await wrapper.vm.$nextTick()
|
|
153
|
+
|
|
154
|
+
expect(wrapper.text()).toContain('too large')
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('validates maximum number of files', async () => {
|
|
158
|
+
const wrapper = createWrapper({ multiple: true, maxFiles: 2 })
|
|
159
|
+
const input = wrapper.find('.dm-file-upload__input')
|
|
160
|
+
|
|
161
|
+
const files = [
|
|
162
|
+
createMockFile('test1.txt', 1024, 'text/plain'),
|
|
163
|
+
createMockFile('test2.txt', 1024, 'text/plain'),
|
|
164
|
+
createMockFile('test3.txt', 1024, 'text/plain')
|
|
165
|
+
]
|
|
166
|
+
|
|
167
|
+
Object.defineProperty(input.element, 'files', {
|
|
168
|
+
value: files,
|
|
169
|
+
writable: false
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
await input.trigger('change')
|
|
173
|
+
await wrapper.vm.$nextTick()
|
|
174
|
+
|
|
175
|
+
expect(wrapper.text()).toContain('Maximum 2 files')
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
it('shows file list when files are selected', async () => {
|
|
179
|
+
const wrapper = createWrapper({ multiple: true })
|
|
180
|
+
const input = wrapper.find('.dm-file-upload__input')
|
|
181
|
+
|
|
182
|
+
const files = [
|
|
183
|
+
createMockFile('test1.txt', 1024, 'text/plain'),
|
|
184
|
+
createMockFile('test2.txt', 2048, 'text/plain')
|
|
185
|
+
]
|
|
186
|
+
|
|
187
|
+
Object.defineProperty(input.element, 'files', {
|
|
188
|
+
value: files,
|
|
189
|
+
writable: false
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
await input.trigger('change')
|
|
193
|
+
|
|
194
|
+
expect(wrapper.find('.dm-file-upload__files').exists()).toBe(true)
|
|
195
|
+
expect(wrapper.findAll('.dm-file-upload__file')).toHaveLength(2)
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('allows file removal', async () => {
|
|
199
|
+
const wrapper = createWrapper({ multiple: true })
|
|
200
|
+
const input = wrapper.find('.dm-file-upload__input')
|
|
201
|
+
|
|
202
|
+
const files = [
|
|
203
|
+
createMockFile('test1.txt', 1024, 'text/plain'),
|
|
204
|
+
createMockFile('test2.txt', 2048, 'text/plain')
|
|
205
|
+
]
|
|
206
|
+
|
|
207
|
+
Object.defineProperty(input.element, 'files', {
|
|
208
|
+
value: files,
|
|
209
|
+
writable: false
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
await input.trigger('change')
|
|
213
|
+
|
|
214
|
+
const removeButton = wrapper.find('.dm-file-upload__remove')
|
|
215
|
+
await removeButton.trigger('click')
|
|
216
|
+
|
|
217
|
+
const fileUpload = wrapper.findComponent(DatametriaFileUpload)
|
|
218
|
+
expect(fileUpload.emitted('update:modelValue')).toBeTruthy()
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
it('supports disabled state', () => {
|
|
222
|
+
const wrapper = createWrapper({ disabled: true })
|
|
223
|
+
const input = wrapper.find('.dm-file-upload__input')
|
|
224
|
+
|
|
225
|
+
expect(input.attributes('disabled')).toBeDefined()
|
|
226
|
+
expect(wrapper.find('.dm-file-upload--disabled').exists()).toBe(true)
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
it('shows loading state during upload', () => {
|
|
230
|
+
const wrapper = createWrapper({ loading: true })
|
|
231
|
+
expect(wrapper.find('.dm-file-upload--loading').exists()).toBe(true)
|
|
232
|
+
expect(wrapper.find('.dm-file-upload__spinner').exists()).toBe(true)
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
it('shows upload progress', () => {
|
|
236
|
+
const wrapper = createWrapper({ progress: 50 })
|
|
237
|
+
const progressBar = wrapper.find('.dm-file-upload__progress-bar')
|
|
238
|
+
|
|
239
|
+
expect(progressBar.exists()).toBe(true)
|
|
240
|
+
expect(progressBar.attributes('style')).toContain('width: 50%')
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
it('supports custom upload text', () => {
|
|
244
|
+
const customText = 'Drop your files here'
|
|
245
|
+
const wrapper = createWrapper({ uploadText: customText })
|
|
246
|
+
|
|
247
|
+
expect(wrapper.find('.dm-file-upload__text').text()).toContain(customText)
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
it('supports custom error messages', () => {
|
|
251
|
+
const errorMessage = 'Upload failed'
|
|
252
|
+
const wrapper = createWrapper({ error: errorMessage })
|
|
253
|
+
|
|
254
|
+
expect(wrapper.find('.dm-file-upload__error').text()).toBe(errorMessage)
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
it('emits file-added event', async () => {
|
|
258
|
+
const wrapper = createWrapper()
|
|
259
|
+
const input = wrapper.find('.dm-file-upload__input')
|
|
260
|
+
const file = createMockFile('test.txt', 1024, 'text/plain')
|
|
261
|
+
|
|
262
|
+
Object.defineProperty(input.element, 'files', {
|
|
263
|
+
value: [file],
|
|
264
|
+
writable: false
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
await input.trigger('change')
|
|
268
|
+
|
|
269
|
+
const fileUpload = wrapper.findComponent(DatametriaFileUpload)
|
|
270
|
+
expect(fileUpload.emitted('file-added')).toBeTruthy()
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
it('emits file-removed event', async () => {
|
|
274
|
+
const wrapper = createWrapper({ multiple: true })
|
|
275
|
+
const input = wrapper.find('.dm-file-upload__input')
|
|
276
|
+
|
|
277
|
+
const files = [createMockFile('test.txt', 1024, 'text/plain')]
|
|
278
|
+
Object.defineProperty(input.element, 'files', {
|
|
279
|
+
value: files,
|
|
280
|
+
writable: false
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
await input.trigger('change')
|
|
284
|
+
|
|
285
|
+
const removeButton = wrapper.find('.dm-file-upload__remove')
|
|
286
|
+
await removeButton.trigger('click')
|
|
287
|
+
|
|
288
|
+
const fileUpload = wrapper.findComponent(DatametriaFileUpload)
|
|
289
|
+
expect(fileUpload.emitted('file-removed')).toBeTruthy()
|
|
290
|
+
})
|
|
291
291
|
})
|