77 lines
2.7 KiB
TypeScript
77 lines
2.7 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { pollVisible } from '../../src/lib/ui/poll.js';
|
|
|
|
let documentStub: EventTarget & { visibilityState: string };
|
|
let stop: (() => void) | undefined;
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
documentStub = Object.assign(new EventTarget(), { visibilityState: 'visible' });
|
|
vi.stubGlobal('document', documentStub);
|
|
});
|
|
afterEach(() => {
|
|
stop?.();
|
|
stop = undefined;
|
|
vi.useRealTimers();
|
|
vi.unstubAllGlobals();
|
|
vi.restoreAllMocks();
|
|
});
|
|
const visibility = (state: string) => {
|
|
documentStub.visibilityState = state;
|
|
documentStub.dispatchEvent(new Event('visibilitychange'));
|
|
};
|
|
|
|
describe('visible page polling', () => {
|
|
it('waits for a request to finish before scheduling the next request', async () => {
|
|
let finish!: () => void;
|
|
const task = vi.fn(
|
|
() =>
|
|
new Promise<void>((resolve) => {
|
|
finish = resolve;
|
|
})
|
|
);
|
|
stop = pollVisible(task, 1000);
|
|
await vi.advanceTimersByTimeAsync(5000);
|
|
visibility('visible');
|
|
expect(task).toHaveBeenCalledTimes(1);
|
|
finish();
|
|
await vi.advanceTimersByTimeAsync(999);
|
|
expect(task).toHaveBeenCalledTimes(1);
|
|
await vi.advanceTimersByTimeAsync(1);
|
|
expect(task).toHaveBeenCalledTimes(2);
|
|
});
|
|
it('pauses when hidden and refreshes on return, including hiding during a request', async () => {
|
|
let finish!: () => void;
|
|
const task = vi.fn(
|
|
() =>
|
|
new Promise<void>((resolve) => {
|
|
finish = resolve;
|
|
})
|
|
);
|
|
stop = pollVisible(task, 1000);
|
|
visibility('hidden');
|
|
finish();
|
|
await vi.advanceTimersByTimeAsync(5000);
|
|
expect(task).toHaveBeenCalledTimes(1);
|
|
visibility('visible');
|
|
expect(task).toHaveBeenCalledTimes(2);
|
|
finish();
|
|
stop();
|
|
visibility('visible');
|
|
await vi.advanceTimersByTimeAsync(5000);
|
|
expect(task).toHaveBeenCalledTimes(2);
|
|
});
|
|
it('recovers after a failed request and supports a delayed initial refresh', async () => {
|
|
vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
const task = vi
|
|
.fn()
|
|
.mockRejectedValueOnce(new Error('offline'))
|
|
.mockResolvedValue(undefined);
|
|
stop = pollVisible(task, 1000, false);
|
|
expect(task).not.toHaveBeenCalled();
|
|
await vi.advanceTimersByTimeAsync(2000);
|
|
expect(task).toHaveBeenCalledTimes(1);
|
|
await vi.advanceTimersByTimeAsync(1000);
|
|
expect(task).toHaveBeenCalledTimes(2);
|
|
});
|
|
});
|