Files
erika/lib/realtime/realtime-refresh.test.ts
T

69 lines
2.1 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import {
matchesRealtimeRefresh,
startRealtimeRefresh,
type RealtimeRefreshEvent,
} from "@/lib/realtime/realtime-refresh";
function waitForRefresh() {
return new Promise((resolve) => setTimeout(resolve, 5));
}
describe("realtime refresh policy", () => {
test("matches page intent against one event stream", () => {
expect(matchesRealtimeRefresh({ kind: "profile" }, { kind: "xp" })).toBeTrue();
expect(matchesRealtimeRefresh({ kind: "profile" }, { kind: "vc", channelId: "1" })).toBeTrue();
expect(matchesRealtimeRefresh({ kind: "vc", channelId: "1" }, { kind: "vc", channelId: "2" })).toBeFalse();
expect(matchesRealtimeRefresh({ kind: "form", formId: "form-1" }, { kind: "form", formId: "form-2" })).toBeFalse();
expect(matchesRealtimeRefresh({ kind: "uploads" }, { kind: "upload" })).toBeTrue();
});
test("refreshes for matching events and reconnects", async () => {
let emit: ((event: RealtimeRefreshEvent) => void) | undefined;
let refreshes = 0;
const clean = startRealtimeRefresh({
filter: { kind: "profile" },
debounceMs: 0,
refresh: () => { refreshes += 1; },
subscribe: (nextEmit) => {
emit = nextEmit;
return { clean() {} };
},
});
emit?.({ kind: "open" });
emit?.({ kind: "xp" });
await waitForRefresh();
emit?.({ kind: "vc", channelId: "1234567890" });
await waitForRefresh();
emit?.({ kind: "open" });
await waitForRefresh();
expect(refreshes).toBe(3);
clean();
});
test("debounces event bursts and cancels on cleanup", async () => {
let emit: ((event: RealtimeRefreshEvent) => void) | undefined;
let refreshes = 0;
const clean = startRealtimeRefresh({
filter: { kind: "xp" },
debounceMs: 1,
refresh: () => { refreshes += 1; },
subscribe: (nextEmit) => {
emit = nextEmit;
return { clean() {} };
},
});
emit?.({ kind: "xp" });
emit?.({ kind: "xp" });
await waitForRefresh();
expect(refreshes).toBe(1);
emit?.({ kind: "xp" });
clean();
await waitForRefresh();
expect(refreshes).toBe(1);
});
});