重构(应用状态存储): 调整savePaths返回结构化结果并更新所有调用处

- 新增SaveResult类型统一标准化保存操作的结果状态
- 修改savePaths函数返回结构化结果而非布尔值,完善长路径超限、部分失败等场景的处理逻辑,部分失败时重新加载路径避免状态偏移
- 更新useAppActions与ProfileDialog的保存逻辑,适配新API并添加长路径确认弹窗
- 补充相关测试用例,修正导入导出测试的版本号预期
This commit is contained in:
2026-05-31 14:48:03 +08:00
parent 78439a6ac6
commit a9b36a6f47
6 changed files with 73 additions and 24 deletions
+20 -6
View File
@@ -208,21 +208,22 @@ describe('useAppActions', () => {
it('handleSave 正常保存', async () => {
mockedInvoke.mockResolvedValue(undefined);
vi.spyOn(useAppStore.getState(), 'savePaths').mockResolvedValue({ kind: 'success' });
const { useAppActions } = await import('@/hooks/use-app-actions');
const { result } = renderHook(() => useAppActions('system', dialogs));
await act(async () => { await result.current.handleSave(); });
// invoke 被调用(backup + save_system + save_user + broadcast
expect(mockedInvoke).toHaveBeenCalled();
// savePaths is called
expect(useAppStore.getState().savePaths).toHaveBeenCalled();
});
it('handleSave 超长确认后强制保存', async () => {
// 第一次 savePaths 返回 false(超长)
// 第二次(force=true)返回 true
// 第一次 savePaths 返回 warning(超长)
// 第二次(force=true)返回 success
let callCount = 0;
vi.spyOn(useAppStore.getState(), 'savePaths').mockImplementation(async (force?: boolean) => {
callCount++;
if (!force) return false; // 第一次:超长警告
return true; // 第二次:强制保存成功
if (!force) return { kind: 'warning', reason: 'lengthExceeded' }; // 第一次:超长警告
return { kind: 'success' }; // 第二次:强制保存成功
});
const { useAppActions } = await import('@/hooks/use-app-actions');
const { result } = renderHook(() => useAppActions('system', dialogs));
@@ -230,4 +231,17 @@ describe('useAppActions', () => {
expect(callCount).toBe(2);
expect(mockAsk).toHaveBeenCalled();
});
it('handleSave 普通失败不弹确认框', async () => {
let callCount = 0;
vi.spyOn(useAppStore.getState(), 'savePaths').mockImplementation(async () => {
callCount++;
return { kind: 'failure', message: '权限不足' };
});
const { useAppActions } = await import('@/hooks/use-app-actions');
const { result } = renderHook(() => useAppActions('system', dialogs));
await act(async () => { await result.current.handleSave(); });
expect(callCount).toBe(1); // 仅调用一次,不重试
expect(mockAsk).not.toHaveBeenCalled();
});
});