feat(upload): validate MIME type and size on file replace in DocumentEditLayout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-18 16:15:22 +02:00
committed by marcel
parent b0ea5f5552
commit d31ea12086
6 changed files with 59 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
import { describe, it, expect } from 'vitest';
import { validateFile, MAX_SIZE_BYTES } from './validateFile';
function makeFile(type: string, size: number): File {
return new File(['x'.repeat(Math.min(size, 100))], 'test.file', { type });
}
describe('validateFile', () => {
it('returns null for a valid PDF under 50 MB', () => {
const file = makeFile('application/pdf', 1024);
expect(validateFile(file)).toBeNull();
});
it('returns null for a valid JPEG', () => {
expect(validateFile(makeFile('image/jpeg', 1024))).toBeNull();
});
it('returns null for a valid PNG', () => {
expect(validateFile(makeFile('image/png', 1024))).toBeNull();
});
it('returns null for a valid TIFF', () => {
expect(validateFile(makeFile('image/tiff', 1024))).toBeNull();
});
it('returns "type" for an unsupported MIME type', () => {
const file = makeFile('text/plain', 100);
expect(validateFile(file)).toBe('type');
});
it('returns "size" for a file exceeding 50 MB', () => {
const oversized = new File(['x'], 'big.pdf', { type: 'application/pdf' });
Object.defineProperty(oversized, 'size', { value: MAX_SIZE_BYTES + 1 });
expect(validateFile(oversized)).toBe('size');
});
});

View File

@@ -0,0 +1,10 @@
export const ALLOWED_TYPES = new Set(['application/pdf', 'image/jpeg', 'image/png', 'image/tiff']);
export const MAX_SIZE_BYTES = 50 * 1024 * 1024;
export type FileValidationError = 'type' | 'size';
export function validateFile(file: File): FileValidationError | null {
if (!ALLOWED_TYPES.has(file.type)) return 'type';
if (file.size > MAX_SIZE_BYTES) return 'size';
return null;
}