UNPKG

@datametria/vue-components

Version:

DATAMETRIA Vue.js 3 Component Library with Multi-Brand Theming - 51 components + 10 composables with theming support, WCAG 2.2 AA, dark mode, responsive system

291 lines (224 loc) 9.01 kB
import { describe, it, expect, vi, beforeEach } from 'vitest' import { mount } from '@vue/test-utils' import DatametriaFileUpload from '../DatametriaFileUpload.vue' import { datametriaTheme } from '../../theme/presets' import { THEME_INJECTION_KEY } from '../../theme/constants' const createWrapper = (props = {}, themeProps = {}) => { return mount(DatametriaFileUpload, { props, global: { plugins: [{ install(app) { app.provide(THEME_INJECTION_KEY, datametriaTheme) } }] } }) } // Mock File API const createMockFile = (name: string, size: number, type: string) => { const file = new File([''], name, { type }) Object.defineProperty(file, 'size', { value: size }) return file } describe('DatametriaFileUpload', () => { beforeEach(() => { vi.clearAllMocks() }) it('renders correctly', () => { const wrapper = createWrapper() expect(wrapper.find('.dm-file-upload').exists()).toBe(true) }) it('applies theme colors correctly', () => { const wrapper = createWrapper() expect(wrapper.find('.dm-file-upload').exists()).toBe(true) }) it('displays upload area', () => { const wrapper = createWrapper() expect(wrapper.find('.dm-file-upload__area').exists()).toBe(true) }) it('shows upload text and icon', () => { const wrapper = createWrapper() expect(wrapper.find('.dm-file-upload__icon').exists()).toBe(true) expect(wrapper.find('.dm-file-upload__text').exists()).toBe(true) }) it('handles file selection via input', async () => { const wrapper = createWrapper() const input = wrapper.find('.dm-file-upload__input') const file = createMockFile('test.txt', 1024, 'text/plain') Object.defineProperty(input.element, 'files', { value: [file], writable: false }) await input.trigger('change') const fileUpload = wrapper.findComponent(DatametriaFileUpload) expect(fileUpload.emitted('update:modelValue')).toBeTruthy() }) it('handles drag and drop', async () => { const wrapper = createWrapper() const dropArea = wrapper.find('.dm-file-upload__area') const file = createMockFile('test.txt', 1024, 'text/plain') const mockDataTransfer = { files: [file] } await dropArea.trigger('drop', { dataTransfer: mockDataTransfer }) const fileUpload = wrapper.findComponent(DatametriaFileUpload) expect(fileUpload.emitted('update:modelValue')).toBeTruthy() }) it('shows drag over state', async () => { const wrapper = createWrapper() const dropArea = wrapper.find('.dm-file-upload__area') await dropArea.trigger('dragenter') await wrapper.vm.$nextTick() expect(wrapper.find('.dm-file-upload__area--dragover').exists()).toBe(true) await dropArea.trigger('dragleave', { relatedTarget: document.body }) await wrapper.vm.$nextTick() expect(wrapper.find('.dm-file-upload__area--dragover').exists()).toBe(false) }) it('supports multiple file selection', async () => { const wrapper = createWrapper({ multiple: true }) const input = wrapper.find('.dm-file-upload__input') expect(input.attributes('multiple')).toBeDefined() const files = [ createMockFile('test1.txt', 1024, 'text/plain'), createMockFile('test2.txt', 2048, 'text/plain') ] Object.defineProperty(input.element, 'files', { value: files, writable: false }) await input.trigger('change') const fileUpload = wrapper.findComponent(DatametriaFileUpload) expect(fileUpload.emitted('update:modelValue')).toBeTruthy() }) it('validates file types', async () => { const wrapper = createWrapper({ accept: '.txt,.pdf' }) const input = wrapper.find('.dm-file-upload__input') expect(input.attributes('accept')).toBe('.txt,.pdf') const invalidFile = createMockFile('test.jpg', 1024, 'image/jpeg') Object.defineProperty(input.element, 'files', { value: [invalidFile], writable: false }) await input.trigger('change') await wrapper.vm.$nextTick() expect(wrapper.text()).toContain('Invalid file type') }) it('validates file size', async () => { const wrapper = createWrapper({ maxSize: 1024 }) // 1KB const input = wrapper.find('.dm-file-upload__input') const largeFile = createMockFile('large.txt', 2048, 'text/plain') // 2KB Object.defineProperty(input.element, 'files', { value: [largeFile], writable: false }) await input.trigger('change') await wrapper.vm.$nextTick() expect(wrapper.text()).toContain('too large') }) it('validates maximum number of files', async () => { const wrapper = createWrapper({ multiple: true, maxFiles: 2 }) const input = wrapper.find('.dm-file-upload__input') const files = [ createMockFile('test1.txt', 1024, 'text/plain'), createMockFile('test2.txt', 1024, 'text/plain'), createMockFile('test3.txt', 1024, 'text/plain') ] Object.defineProperty(input.element, 'files', { value: files, writable: false }) await input.trigger('change') await wrapper.vm.$nextTick() expect(wrapper.text()).toContain('Maximum 2 files') }) it('shows file list when files are selected', async () => { const wrapper = createWrapper({ multiple: true }) const input = wrapper.find('.dm-file-upload__input') const files = [ createMockFile('test1.txt', 1024, 'text/plain'), createMockFile('test2.txt', 2048, 'text/plain') ] Object.defineProperty(input.element, 'files', { value: files, writable: false }) await input.trigger('change') expect(wrapper.find('.dm-file-upload__files').exists()).toBe(true) expect(wrapper.findAll('.dm-file-upload__file')).toHaveLength(2) }) it('allows file removal', async () => { const wrapper = createWrapper({ multiple: true }) const input = wrapper.find('.dm-file-upload__input') const files = [ createMockFile('test1.txt', 1024, 'text/plain'), createMockFile('test2.txt', 2048, 'text/plain') ] Object.defineProperty(input.element, 'files', { value: files, writable: false }) await input.trigger('change') const removeButton = wrapper.find('.dm-file-upload__remove') await removeButton.trigger('click') const fileUpload = wrapper.findComponent(DatametriaFileUpload) expect(fileUpload.emitted('update:modelValue')).toBeTruthy() }) it('supports disabled state', () => { const wrapper = createWrapper({ disabled: true }) const input = wrapper.find('.dm-file-upload__input') expect(input.attributes('disabled')).toBeDefined() expect(wrapper.find('.dm-file-upload--disabled').exists()).toBe(true) }) it('shows loading state during upload', () => { const wrapper = createWrapper({ loading: true }) expect(wrapper.find('.dm-file-upload--loading').exists()).toBe(true) expect(wrapper.find('.dm-file-upload__spinner').exists()).toBe(true) }) it('shows upload progress', () => { const wrapper = createWrapper({ progress: 50 }) const progressBar = wrapper.find('.dm-file-upload__progress-bar') expect(progressBar.exists()).toBe(true) expect(progressBar.attributes('style')).toContain('width: 50%') }) it('supports custom upload text', () => { const customText = 'Drop your files here' const wrapper = createWrapper({ uploadText: customText }) expect(wrapper.find('.dm-file-upload__text').text()).toContain(customText) }) it('supports custom error messages', () => { const errorMessage = 'Upload failed' const wrapper = createWrapper({ error: errorMessage }) expect(wrapper.find('.dm-file-upload__error').text()).toBe(errorMessage) }) it('emits file-added event', async () => { const wrapper = createWrapper() const input = wrapper.find('.dm-file-upload__input') const file = createMockFile('test.txt', 1024, 'text/plain') Object.defineProperty(input.element, 'files', { value: [file], writable: false }) await input.trigger('change') const fileUpload = wrapper.findComponent(DatametriaFileUpload) expect(fileUpload.emitted('file-added')).toBeTruthy() }) it('emits file-removed event', async () => { const wrapper = createWrapper({ multiple: true }) const input = wrapper.find('.dm-file-upload__input') const files = [createMockFile('test.txt', 1024, 'text/plain')] Object.defineProperty(input.element, 'files', { value: files, writable: false }) await input.trigger('change') const removeButton = wrapper.find('.dm-file-upload__remove') await removeButton.trigger('click') const fileUpload = wrapper.findComponent(DatametriaFileUpload) expect(fileUpload.emitted('file-removed')).toBeTruthy() }) })