fix(RouterProvider): 修复初始加载状态逻辑,确保在加载前不覆盖 chrome.storage
- 将 isLoaded 的初始状态设置为 false,避免在加载初始数据前错误地覆盖存储。 - 新增测试用例,验证在 localStorage 快照过期时,loadInitialData 完成前不应覆盖 chrome.storage 的行为。
This commit is contained in:
@@ -104,12 +104,7 @@ export function RouterProvider({
|
||||
getSyncSnapshot('app/recentlyUsedTools', [], isValidPageList),
|
||||
);
|
||||
|
||||
const [isLoaded, setIsLoaded] = useState(() => {
|
||||
const snapshotKey = localStorage.getItem(`snapshot/${syncKey as string}`);
|
||||
const snapshotVisible = localStorage.getItem(`snapshot/${visiblePagesKey as string}`);
|
||||
const snapshotOrder = localStorage.getItem(`snapshot/${pageOrderKey as string}`);
|
||||
return !!(snapshotKey && snapshotVisible && snapshotOrder);
|
||||
});
|
||||
const [isLoaded, setIsLoaded] = useState(false);
|
||||
|
||||
/**
|
||||
* 从异步存储中安全溯源初始数据
|
||||
|
||||
@@ -277,6 +277,52 @@ describe('RouterProvider', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('localStorage 快照过期时,loadInitialData 完成前不应覆盖 chrome.storage', async () => {
|
||||
const staleRoute = 'timestamp';
|
||||
const correctRoute = 'jsonTools';
|
||||
const defaultVisible = ['dashboard', 'timestamp', 'storageCleaner'];
|
||||
const defaultOrder = ['timestamp', 'storageCleaner'];
|
||||
|
||||
localStorage.setItem('snapshot/app/currentRoute', JSON.stringify(staleRoute));
|
||||
localStorage.setItem('snapshot/app/visiblePages', JSON.stringify(defaultVisible));
|
||||
localStorage.setItem('snapshot/app/pageOrder', JSON.stringify(defaultOrder));
|
||||
|
||||
const storage = new Map<string, unknown>([
|
||||
['app/currentRoute', correctRoute],
|
||||
['app/visiblePages', defaultVisible],
|
||||
['app/pageOrder', defaultOrder],
|
||||
['app/recentlyUsedTools', []],
|
||||
]);
|
||||
|
||||
let resolveGet: () => void;
|
||||
const getBlocked = new Promise<void>((resolve) => {
|
||||
resolveGet = resolve;
|
||||
});
|
||||
|
||||
(storageUtil.get as any).mockImplementation(async (key: string, defaultValue: unknown) => {
|
||||
await getBlocked;
|
||||
return storage.get(key) ?? defaultValue;
|
||||
});
|
||||
(storageUtil.set as any).mockImplementation(async (key: string, value: unknown) => {
|
||||
storage.set(key, value);
|
||||
});
|
||||
|
||||
render(
|
||||
<RouterProvider>
|
||||
<TestComponent />
|
||||
</RouterProvider>,
|
||||
);
|
||||
|
||||
expect(screen.getByTestId('current-page')).toHaveTextContent(staleRoute);
|
||||
expect(storageUtil.set).not.toHaveBeenCalledWith('app/currentRoute', staleRoute);
|
||||
|
||||
resolveGet!();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('current-page')).toHaveTextContent(correctRoute);
|
||||
expect(storage.get('app/currentRoute')).toBe(correctRoute);
|
||||
});
|
||||
});
|
||||
|
||||
it('组件卸载时不应设置 isLoaded 状态(竞态条件防护)', async () => {
|
||||
let resolveStorage: (value: unknown) => void;
|
||||
const storagePromise = new Promise((resolve) => {
|
||||
|
||||
Reference in New Issue
Block a user