Files
Literature-Management/tests/unit/main/notes-filename-validator.test.ts
2026-10-21 14:42:59 +08:00

63 lines
2.6 KiB
TypeScript

// tests/unit/main/notes-filename-validator.test.ts
//
// 守 note 文件名校验契约 —— audit-r170 把圆括号放行(副本默认名
// 「X (copy).md」/「X (copy 2).md」是 Windows 资源管理器同款约定),
// 旧 regex 不收 '(' ')' → 每一次「复制 → 粘贴」都抛 ValidationError。
// 本文件锁住:
// - 圆括号(中段 / 段首)合法
// - 路径穿越形态('..'、绝对路径)仍被拒
// - 保留设备名 / 超长名仍被拒
// - .md / .markdown 两后缀都收
import { describe, expect, it } from 'vitest';
import {
normalizeAndValidateNoteFilename,
NOTE_FILENAME_MAX_LENGTH,
} from '../../../src/main/notes/filename-validator';
import { ValidationError } from '../../../src/main/utils/error';
describe('notes filename-validator', () => {
it('r170:圆括号副本名合法(中段)', () => {
expect(normalizeAndValidateNoteFilename('foo (copy).md', 'filename')).toBe('foo (copy).md');
expect(normalizeAndValidateNoteFilename('foo (copy 2).md', 'filename')).toBe('foo (copy 2).md');
expect(normalizeAndValidateNoteFilename('会议纪要 (副本).md', 'filename')).toBe(
'会议纪要 (副本).md',
);
});
it('r170:圆括号在段首也合法(OS 拖入「(1) 会议纪要.md」)', () => {
expect(normalizeAndValidateNoteFilename('(1) 会议纪要.md', 'filename')).toBe(
'(1) 会议纪要.md',
);
});
it('r170:嵌套路径(带目录前缀)仍合法 —— 副本直接建在目标目录靠它', () => {
expect(normalizeAndValidateNoteFilename('sub/foo (copy).md', 'filename')).toBe(
'sub/foo (copy).md',
);
});
it('路径穿越形态仍被拒', () => {
expect(() => normalizeAndValidateNoteFilename('../evil.md', 'filename')).toThrow(ValidationError);
expect(() => normalizeAndValidateNoteFilename('a/../../evil.md', 'filename')).toThrow(
ValidationError,
);
});
it('保留设备名仍被拒(每段都查)', () => {
expect(() => normalizeAndValidateNoteFilename('con.md', 'filename')).toThrow(ValidationError);
expect(() => normalizeAndValidateNoteFilename('sub/con.md', 'filename')).toThrow(
ValidationError,
);
});
it('超长名仍被拒', () => {
const long = `${'a'.repeat(NOTE_FILENAME_MAX_LENGTH + 1)}.md`;
expect(() => normalizeAndValidateNoteFilename(long, 'filename')).toThrow(ValidationError);
});
it('.md / .markdown 两后缀都收,缺后缀自动补 .md', () => {
expect(normalizeAndValidateNoteFilename('foo', 'filename')).toBe('foo.md');
expect(normalizeAndValidateNoteFilename('foo.markdown', 'filename')).toBe('foo.markdown');
});
});