刷新时先撤掉待触发的自动保存,避免旧值被写回注册表

- load() 在读盘前就把 dirty 归零:原来要等读回来的那一刻才归零,若这次读得比停止输入的 600ms 还慢,等待中的自动保存会先到点,把用户手里那份旧值写回注册表,随后刷新又用读到的内容盖掉界面,两边都不一致。
- 新增一例回归用例:第二次读(点刷新那次)故意慢 1200ms,越过自动保存的延时后断言没有发出 save_xhs_minitool_export_form,且界面回到磁盘上的值。已验证去掉修复后这例失败。
This commit is contained in:
2026-10-05 17:26:46 +08:00
parent 75ff9ca75b
commit 90f651ddfe
2 changed files with 39 additions and 1 deletions
@@ -84,6 +84,8 @@ export function useXhsMinitoolExport({
return; return;
} }
setLoading(true); setLoading(true);
// 刷新以磁盘为准:先撤掉还在等待触发的自动保存,否则读盘期间那一次保存会把旧值写回去。
setDirty(false);
try { try {
const state = await readXhsMinitoolExport(invoke, projectPath); const state = await readXhsMinitoolExport(invoke, projectPath);
setForm(state.form); setForm(state.form);
@@ -92,7 +94,6 @@ export function useXhsMinitoolExport({
setFieldError(null); setFieldError(null);
setConflict(null); setConflict(null);
setFailure(null); setFailure(null);
setDirty(false);
} catch (error) { } catch (error) {
const structured = asXhsMinitoolFailure(error); const structured = asXhsMinitoolFailure(error);
if (structured) setFailure(failureState(structured)); if (structured) setFailure(failureState(structured));
@@ -276,6 +276,43 @@ describe('状态 hook', () => {
); );
}); });
it('刷新期间不再把待保存的旧值写回去', async () => {
let reads = 0;
const invoke = vi.fn(async (command: string) => {
if (command !== 'read_xhs_minitool_export') return {};
reads += 1;
// 第二次读(点刷新那次)故意慢:让停止输入后的自动保存在读盘期间到点。
if (reads > 1) {
await new Promise((resolve) => setTimeout(resolve, 1200));
}
return { form: FORM, hasScript: true, contentHash: CONTENT_HASH };
});
installTauriRuntime({ core: { invoke } });
const { result } = renderHook(() =>
useXhsMinitoolExport({
enabled: true,
projectPath: PROJECT_PATH,
submitTurn: vi.fn(async () => true),
}),
);
await waitFor(() => expect(result.current.form).toEqual(FORM));
await act(async () => {
result.current.updateField('name', '新名字');
void result.current.load();
});
// 越过自动保存的 600ms:刷新以磁盘为准,这份还没保存的输入不该再落盘。
await act(async () => {
await new Promise((resolve) => setTimeout(resolve, 1500));
});
expect(invoke).not.toHaveBeenCalledWith(
'save_xhs_minitool_export_form',
expect.anything(),
);
expect(result.current.form).toEqual(FORM);
});
it('导出把打包脚本的输出尾部一并报给用户', async () => { it('导出把打包脚本的输出尾部一并报给用户', async () => {
const invoke = vi.fn(async (command: string) => { const invoke = vi.fn(async (command: string) => {
if (command === 'read_xhs_minitool_export') { if (command === 'read_xhs_minitool_export') {