// @vitest-environment jsdom import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { render, screen, fireEvent, waitFor, cleanup } from '@testing-library/react'; import { AvatarUpload } from './AvatarUpload'; import type { WidgetTranslations } from '../i18n'; const { fileToBase64, resizeAvatarImage } = vi.hoisted( () => ( { fileToBase64: vi.fn(), resizeAvatarImage: vi.fn(), } ) ); vi.mock( '../imageUtils', () => ( { fileToBase64, resizeAvatarImage, // Real class so `instanceof` works in the component. UndecodableImageError: class UndecodableImageError extends Error {}, } ) ); // Minimal `upload` translations for the component under test. const T = { invalidFile: 'INVALID', processingFailed: 'PROC_FAILED', unreadableImage: 'UNREADABLE', } as unknown as WidgetTranslations[ 'upload' ]; function selectFile( type = 'image/png' ): void { const input = document.querySelector( 'input[type="file"]' ) as HTMLInputElement; const file = new File( [ 'bytes' ], 'photo', { type } ); fireEvent.change( input, { target: { files: [ file ] } } ); } beforeEach( () => { fileToBase64.mockReset().mockResolvedValue( 'data:image/png;base64,SRC' ); resizeAvatarImage.mockReset(); } ); afterEach( () => { cleanup(); } ); describe( 'AvatarUpload accepts anything decodable, refuses only undecodable', () => { it( 'shows the unreadable message when decode fails', async () => { const { UndecodableImageError } = await import( '../imageUtils' ); resizeAvatarImage.mockRejectedValue( new ( UndecodableImageError as any )() ); render( ); selectFile( 'application/octet-stream' ); // odd type must still be attempted await waitFor( () => expect( screen.getByText( 'UNREADABLE' ) ).toBeTruthy() ); expect( resizeAvatarImage ).toHaveBeenCalled(); // no MIME gate blocked it } ); it( 'processes a decodable file without a size/format refusal', async () => { resizeAvatarImage.mockResolvedValue( 'data:image/jpeg;base64,SMALL' ); render( ); selectFile( 'image/webp' ); await waitFor( () => expect( resizeAvatarImage ).toHaveBeenCalledWith( 'data:image/png;base64,SRC' ) ); expect( screen.queryByText( 'INVALID' ) ).toBeNull(); } ); } );