47 lines
1.1 KiB
TypeScript
47 lines
1.1 KiB
TypeScript
|
|
import {
|
||
|
|
resetRefreshLockForTests,
|
||
|
|
withRefreshLock,
|
||
|
|
} from '@/core/auth/refresh-lock';
|
||
|
|
|
||
|
|
describe('withRefreshLock', () => {
|
||
|
|
beforeEach(() => {
|
||
|
|
resetRefreshLockForTests();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('runs concurrent callers through a single in-flight refresh', async () => {
|
||
|
|
let runs = 0;
|
||
|
|
const fn = jest.fn(async () => {
|
||
|
|
runs += 1;
|
||
|
|
await new Promise((resolve) => setTimeout(resolve, 20));
|
||
|
|
return 'ok';
|
||
|
|
});
|
||
|
|
|
||
|
|
const [a, b, c] = await Promise.all([
|
||
|
|
withRefreshLock(fn),
|
||
|
|
withRefreshLock(fn),
|
||
|
|
withRefreshLock(fn),
|
||
|
|
]);
|
||
|
|
|
||
|
|
expect(a).toBe('ok');
|
||
|
|
expect(b).toBe('ok');
|
||
|
|
expect(c).toBe('ok');
|
||
|
|
expect(fn).toHaveBeenCalledTimes(1);
|
||
|
|
expect(runs).toBe(1);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('propagates errors to queued waiters', async () => {
|
||
|
|
const fn = jest.fn(async () => {
|
||
|
|
throw new Error('refresh failed');
|
||
|
|
});
|
||
|
|
|
||
|
|
const results = await Promise.allSettled([
|
||
|
|
withRefreshLock(fn),
|
||
|
|
withRefreshLock(fn),
|
||
|
|
]);
|
||
|
|
|
||
|
|
expect(fn).toHaveBeenCalledTimes(1);
|
||
|
|
expect(results[0].status).toBe('rejected');
|
||
|
|
expect(results[1].status).toBe('rejected');
|
||
|
|
});
|
||
|
|
});
|