Files
av-tools/tests/unit/media/safe-file-name.test.ts

54 lines
1.7 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
createSafeVirtualFileName,
safeFileName,
safeOutputFileName,
splitFileName,
} from '../../../src/media/safe-file-name';
describe('safe filenames', () => {
it('removes path traversal, control characters and shell-like punctuation', () => {
expect(safeFileName('../../My $ video\u0000 (final).MP4')).toBe(
'My-video-final.mp4'
);
expect(safeFileName('..\\..\\evil.webm')).toBe('evil.webm');
expect(safeFileName('../')).toBe('file');
});
it('handles Unicode, hidden names and reserved device names', () => {
expect(safeFileName('Crème brûlée.mov')).toBe('Creme-brulee.mov');
expect(safeFileName('.env')).toBe('env');
expect(safeFileName('CON.mp4')).toBe('_CON.mp4');
});
it('preserves a short extension while enforcing the requested maximum', () => {
const result = safeFileName(`${'a'.repeat(200)}.mp4`, {
maxLength: 32,
});
expect(result).toHaveLength(32);
expect(result.endsWith('.mp4')).toBe(true);
});
it('creates generated virtual names without leaking the original stem', () => {
expect(createSafeVirtualFileName('private-holiday.mov', 3)).toBe(
'source-3.mov'
);
expect(() => createSafeVirtualFileName('x.mp4', -1)).toThrow();
});
it('creates deterministic download names and splits compound extensions', () => {
expect(safeOutputFileName('My export (1)', '.WEBM')).toBe(
'My-export-1.webm'
);
expect(safeOutputFileName('Project', 'avproject.json')).toBe(
'Project.avproject.json'
);
expect(safeOutputFileName('Project.v2', 'mp4')).toBe('Project.v2.mp4');
expect(splitFileName('archive.tar.gz')).toEqual({
stem: 'archive.tar',
extension: '.gz',
});
});
});