Files
zcb 8cdaf90d8d refactor: replace JSON deep copy with deepClone helper and extract useTauriEvent hook (#3140)
* refactor: replace JSON.parse(JSON.stringify()) with structuredClone and extract useTauriEvent hook

Replace all `JSON.parse(JSON.stringify())` deep copy patterns with native
`structuredClone()` across production source (9 occurrences), tests (11
occurrences), and a hand-rolled `deepClone` utility in providerConfigUtils.ts.
Add "ES2022" to tsconfig lib for type support.

Extract a `useTauriEvent` hook to eliminate the repeated Tauri event listener
boilerplate (`useEffect` + `active/disposed` flag + async `listen`) that was
duplicated across App.tsx (3 listeners) and useUsageCacheBridge.ts. The hook
handles async registration, race-condition guards, and cleanup automatically.

* fix: add compatible deepClone helper

- Add a shared deepClone helper with a structuredClone runtime guard and fallback.
- Route clone call sites through the helper.
- Preserve universal-provider-synced listener ordering and drop the dead-directory diff.

* fix: harden Tauri event handling

- Guard WebDAV sync status events against missing payloads.
- Preserve settings query invalidation ordering before showing auto-sync errors.
- Simplify useTauriEvent subscriptions to avoid dependency-driven re-listens.

---------

Co-authored-by: zcb <zhangchongbiao@qiyuanlab.com>
Co-authored-by: Jason <farion1231@gmail.com>
2026-05-26 23:39:16 +08:00

31 lines
945 B
TypeScript

import { afterEach, describe, expect, it, vi } from "vitest";
import { deepClone } from "@/utils/deepClone";
describe("deepClone", () => {
afterEach(() => {
vi.unstubAllGlobals();
});
it("falls back when structuredClone is unavailable", () => {
vi.stubGlobal("structuredClone", undefined);
const source = {
nested: { value: "original" },
list: [{ enabled: true }],
createdAt: new Date("2026-01-30T00:00:00.000Z"),
};
const cloned = deepClone(source);
cloned.nested.value = "changed";
cloned.list[0].enabled = false;
expect(cloned).not.toBe(source);
expect(cloned.nested).not.toBe(source.nested);
expect(cloned.list).not.toBe(source.list);
expect(cloned.createdAt).not.toBe(source.createdAt);
expect(cloned.createdAt.getTime()).toBe(source.createdAt.getTime());
expect(source.nested.value).toBe("original");
expect(source.list[0].enabled).toBe(true);
});
});