// @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();
} );
} );