import { describe, it, expect, vi, afterEach } from 'vitest' import { mount } from '@vue/test-utils' import ImageInput from '../ImageInput.vue' function makeFile(name, type, size = 100) { return new File(['x'.repeat(size)], name, { type }) } function setFiles(input, files) { Object.defineProperty(input.element, 'files', { value: files, configurable: true }) } describe('ImageInput', () => { afterEach(() => vi.unstubAllGlobals()) it('renders the drop zone and file input', () => { const wrapper = mount(ImageInput) expect(wrapper.find('label').exists()).toBe(true) expect(wrapper.find('input[type="file"]').exists()).toBe(true) }) it('shows error for non-image file', async () => { const wrapper = mount(ImageInput) const input = wrapper.find('input[type="file"]') setFiles(input, [makeFile('doc.pdf', 'application/pdf')]) await input.trigger('change') expect(wrapper.text()).toContain('Only image files are supported.') }) it('shows error for file exceeding 20 MB', async () => { const wrapper = mount(ImageInput) const input = wrapper.find('input[type="file"]') setFiles(input, [makeFile('big.png', 'image/png', 21 * 1024 * 1024)]) await input.trigger('change') expect(wrapper.text()).toContain('20 MB') }) it('emits image-ready with correct shape on valid image', async () => { class MockFileReader { readAsDataURL() { this.onload({ target: { result: 'data:image/png;base64,abc' } }) } } vi.stubGlobal('FileReader', MockFileReader) const wrapper = mount(ImageInput) const input = wrapper.find('input[type="file"]') setFiles(input, [makeFile('photo.png', 'image/png')]) await input.trigger('change') const emitted = wrapper.emitted('image-ready') expect(emitted).toBeTruthy() expect(emitted[0][0]).toMatchObject({ dataUrl: 'data:image/png;base64,abc', mimeType: 'image/png', filename: 'photo.png', }) }) it('attaches paste listener on mount and removes it on unmount', () => { const add = vi.spyOn(window, 'addEventListener') const remove = vi.spyOn(window, 'removeEventListener') const wrapper = mount(ImageInput) expect(add).toHaveBeenCalledWith('paste', expect.any(Function)) wrapper.unmount() expect(remove).toHaveBeenCalledWith('paste', expect.any(Function)) }) })