镜像自地址
https://github.com/lhly/cloud-drive-renamer.git
已同步 2026-10-20 21:57:47 +08:00
- 在平台适配器中统一暴露 getCurrentDirectoryKey() 方法,用于确定当前目录范围 - 新增 LastRenameOperation 数据模型和核心操作函数,支持单条撤销记录的创建、合并和范围校验 - 在 file-selector-panel 中集成撤销逻辑,支持执行后保存记录、retry 成功后合并记录以及撤销操作 - 在 config-panel 底部操作区新增撤销按钮,根据当前目录范围动态显示/隐藏 - 添加多语言支持,包含撤销相关文案 - 添加单元测试和集成测试,确保撤销功能的正确性和稳定性
75 行
2.9 KiB
TypeScript
75 行
2.9 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
createLastRenameOperation,
|
|
isLastRenameOperationInScope,
|
|
mergeLastRenameOperation,
|
|
retainFailedUndoItems,
|
|
} from '../../src/core/last-rename-operation';
|
|
|
|
describe('last rename operation helpers', () => {
|
|
it('creates a last rename operation from success results', () => {
|
|
const operation = createLastRenameOperation('quark', 'dir-1', [
|
|
{ fileId: '1', original: 'old-a.txt', renamed: 'new-a.txt', index: 0 },
|
|
]);
|
|
|
|
expect(operation).not.toBeNull();
|
|
expect(operation?.platform).toBe('quark');
|
|
expect(operation?.directoryKey).toBe('dir-1');
|
|
expect(operation?.items).toEqual([
|
|
{ fileId: '1', original: 'old-a.txt', renamed: 'new-a.txt', index: 0 },
|
|
]);
|
|
expect(typeof operation?.createdAt).toBe('number');
|
|
expect(typeof operation?.updatedAt).toBe('number');
|
|
});
|
|
|
|
it('returns null when creating from empty success results', () => {
|
|
expect(createLastRenameOperation('quark', 'dir-1', [])).toBeNull();
|
|
});
|
|
|
|
it('merges retry success items into the existing operation', () => {
|
|
const existing = createLastRenameOperation('quark', 'dir-1', [
|
|
{ fileId: '1', original: 'old-a.txt', renamed: 'new-a.txt', index: 0 },
|
|
]);
|
|
|
|
const merged = mergeLastRenameOperation(existing, 'quark', 'dir-1', [
|
|
{ fileId: '2', original: 'old-b.txt', renamed: 'new-b.txt', index: 1 },
|
|
]);
|
|
|
|
expect(merged).not.toBeNull();
|
|
expect(merged?.items.map((item) => item.fileId)).toEqual(['1', '2']);
|
|
expect(merged?.createdAt).toBe(existing?.createdAt);
|
|
expect((merged?.updatedAt ?? 0) >= (existing?.updatedAt ?? 0)).toBe(true);
|
|
});
|
|
|
|
it('checks whether an operation is still in the current scope', () => {
|
|
const operation = createLastRenameOperation('baidu', '/video/season1', [
|
|
{ fileId: '9', original: 'ep01.mkv', renamed: 'S01E01.mkv', index: 0 },
|
|
]);
|
|
|
|
expect(isLastRenameOperationInScope(operation, 'baidu', '/video/season1')).toBe(true);
|
|
expect(isLastRenameOperationInScope(operation, 'baidu', '/video/season2')).toBe(false);
|
|
expect(isLastRenameOperationInScope(operation, 'quark', '/video/season1')).toBe(false);
|
|
});
|
|
|
|
it('retains only failed undo items', () => {
|
|
const operation = createLastRenameOperation('quark', 'dir-1', [
|
|
{ fileId: '1', original: 'old-a.txt', renamed: 'new-a.txt', index: 0 },
|
|
{ fileId: '2', original: 'old-b.txt', renamed: 'new-b.txt', index: 1 },
|
|
]);
|
|
|
|
const next = retainFailedUndoItems(operation, new Set(['2']));
|
|
|
|
expect(next?.items).toEqual([
|
|
{ fileId: '2', original: 'old-b.txt', renamed: 'new-b.txt', index: 1 },
|
|
]);
|
|
});
|
|
|
|
it('returns null when no failed undo items remain', () => {
|
|
const operation = createLastRenameOperation('quark', 'dir-1', [
|
|
{ fileId: '1', original: 'old-a.txt', renamed: 'new-a.txt', index: 0 },
|
|
]);
|
|
|
|
expect(retainFailedUndoItems(operation, new Set())).toBeNull();
|
|
});
|
|
});
|