70 lines
1.7 KiB
TypeScript
70 lines
1.7 KiB
TypeScript
import { vi } from "vitest";
|
|
|
|
export function createDeterministicClock(start = 0) {
|
|
let current = start;
|
|
return Object.freeze({
|
|
now: () => current,
|
|
sleep: async (milliseconds: number, signal?: AbortSignal) => {
|
|
if (signal?.aborted) throw new DOMException("aborted", "AbortError");
|
|
current += Math.max(0, milliseconds);
|
|
},
|
|
advance(milliseconds: number) {
|
|
current += Math.max(0, milliseconds);
|
|
},
|
|
});
|
|
}
|
|
|
|
export function createSeededRandom(seed = 1) {
|
|
let state = seed >>> 0;
|
|
return () => {
|
|
state = (state * 1_664_525 + 1_013_904_223) >>> 0;
|
|
return state / 0x1_0000_0000;
|
|
};
|
|
}
|
|
|
|
export function createControlledScheduler() {
|
|
const callbacks: Array<() => void> = [];
|
|
return Object.freeze({
|
|
callbacks,
|
|
setTimeout: vi.fn((callback: () => void) => {
|
|
callbacks.push(callback);
|
|
return callbacks.length - 1;
|
|
}),
|
|
clearTimeout: vi.fn(),
|
|
runNext() {
|
|
callbacks.shift()?.();
|
|
},
|
|
});
|
|
}
|
|
|
|
export function createRecordingStorage() {
|
|
const values = new Map<string, string>();
|
|
const operations: Array<
|
|
Readonly<{ operation: "get" | "set" | "remove"; key: string }>
|
|
> = [];
|
|
const storage: Storage = {
|
|
getItem(key) {
|
|
operations.push({ operation: "get", key });
|
|
return values.get(key) ?? null;
|
|
},
|
|
setItem(key, value) {
|
|
operations.push({ operation: "set", key });
|
|
values.set(key, value);
|
|
},
|
|
removeItem(key) {
|
|
operations.push({ operation: "remove", key });
|
|
values.delete(key);
|
|
},
|
|
clear() {
|
|
values.clear();
|
|
},
|
|
key(index) {
|
|
return [...values.keys()][index] ?? null;
|
|
},
|
|
get length() {
|
|
return values.size;
|
|
},
|
|
};
|
|
return Object.freeze({ storage, operations, values });
|
|
}
|