cloud-drive-renamer/tests/unit/episode-extract-rule.test.ts
Zain c5b94b57c9 feat(rule): 添加剧集提取规则用于标准化命名
新增 episodeExtract 规则类型,支持从文件名提取季集号并按模板生成新文件名。提取失败的文件会在预览中显示错误信息并自动跳过执行,避免误操作。

- 支持模板变量:{prefix} {season} {episode} {ext}
- 提供 helperPre/helperPost 锚点辅助提取
- 支持集数偏移和自定义前导零位数
- 更新规则工厂、类型定义和国际化配置
- 添加单元测试和设计文档
2026-03-18 08:51:50 +08:00

82 行
2.3 KiB
TypeScript

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

import { describe, it, expect } from 'vitest';
import { EpisodeExtractRule } from '../../src/rules/episode-extract';
describe('EpisodeExtractRule', () => {
it('应按模板输出剧集命名(含 ext)', () => {
const rule = new EpisodeExtractRule({
template: '{prefix}.S{season}E{episode}{ext}',
prefix: 'My.Show',
season: 1,
leadingZeroCount: 3,
});
const result = rule.execute('My.Show.S01E02.1080p.mp4', 0, 1);
expect(result).toBe('My.Show.S01E002.mp4');
});
it('模板未包含 {ext} 时应自动补扩展名', () => {
const rule = new EpisodeExtractRule({
template: '{prefix}.S{season}E{episode}',
prefix: 'Series',
season: 2,
leadingZeroCount: 2,
});
const result = rule.execute('Series.EP7.mkv', 0, 1);
expect(result).toBe('Series.S02E07.mkv');
});
it('应支持 helperPre/helperPost 提取集数', () => {
const rule = new EpisodeExtractRule({
template: '{prefix}-S{season}E{episode}{ext}',
prefix: 'Drama',
season: 3,
helperPre: '第',
helperPost: '集',
leadingZeroCount: 3,
});
const result = rule.execute('Drama 第12集 中文字幕.mp4', 0, 1);
expect(result).toBe('Drama-S03E012.mp4');
});
it('应支持 offset 偏移', () => {
const rule = new EpisodeExtractRule({
template: '{prefix}.S{season}E{episode}{ext}',
prefix: 'Offset',
season: 1,
offset: 10,
leadingZeroCount: 3,
});
const result = rule.execute('Offset EP02.mp4', 0, 1);
expect(result).toBe('Offset.S01E012.mp4');
});
it('提取失败时应抛出“未识别到集数”错误码,供上层展示友好文案', () => {
const rule = new EpisodeExtractRule({
template: '{prefix}.S{season}E{episode}{ext}',
prefix: 'NoEp',
season: 1,
});
expect(() => rule.execute('No episode token here.mp4', 0, 1)).toThrow(
/extract_episode_not_found/
);
});
it('offset 导致集数无效时应抛出范围错误码', () => {
const rule = new EpisodeExtractRule({
template: '{prefix}.S{season}E{episode}{ext}',
prefix: 'OffsetBad',
season: 1,
offset: -10,
leadingZeroCount: 3,
});
expect(() => rule.execute('OffsetBad EP02.mp4', 0, 1)).toThrow(
/extract_episode_out_of_range/
);
});
});