test: check that session restore waits for the persisted stores together

The audit listed the four hydration waits in `restoreSession()` as
serial. They are already awaited together with `Promise.all`, and
restore only reads the stores after all four have settled, so the order
they finish in does not matter. The remaining queueing is inside
AsyncStorage, whose native side runs reads one at a time.

This test pins the concurrent wait: with all four stores stuck, restore
gives up after one `HYDRATION_TIMEOUT_MS`, not four.
This commit is contained in:
Linus Rath
2026-09-24 19:35:47 +02:00
parent 4a5d837cd7
commit 85f23dfdf4
+27
View File
@@ -39,6 +39,8 @@ import { jmapClient } from '../../api/jmap-client';
import { useAuthStore, HYDRATION_TIMEOUT_MS } from '../auth-store';
import { useAccountStore } from '../account-store';
import { useCalendarStore } from '../calendar-store';
import { useContactsStore } from '../contacts-store';
import { useEmailStore } from '../email-store';
const mockConnect = jmapClient.connect as ReturnType<typeof vi.fn>;
const mockLogout = jmapClient.logout as ReturnType<typeof vi.fn>;
@@ -181,6 +183,31 @@ describe('auth-store', () => {
vi.useRealTimers();
}
});
it('waits for the four persisted stores at the same time', async () => {
vi.useFakeTimers();
const warn = vi.spyOn(console, 'warn').mockImplementation(() => undefined);
const spies = [useAccountStore, useEmailStore, useCalendarStore, useContactsStore]
.map((store) => vi.spyOn(store.persist, 'hasHydrated').mockReturnValue(false));
try {
let settled = false;
const restoring = useAuthStore.getState().restoreSession().finally(() => { settled = true; });
// One after another, four stuck stores would hold the session for
// four timeouts; waited on together, they cost one.
await vi.advanceTimersByTimeAsync(HYDRATION_TIMEOUT_MS - 1);
expect(settled).toBe(false);
await vi.advanceTimersByTimeAsync(1);
expect(settled).toBe(true);
expect(await restoring).toBe(false);
expect(warn.mock.calls.filter(([m]) => String(m).includes('did not hydrate in time'))).toHaveLength(4);
} finally {
for (const spy of spies) spy.mockRestore();
warn.mockRestore();
vi.useRealTimers();
}
});
});
describe('clearError', () => {