feat: add realtime Discord leaderboards
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { afterEach, describe, expect, mock, test } from "bun:test";
|
||||
import {
|
||||
startRealtimeRefresh,
|
||||
type RealtimeRefreshHandlers,
|
||||
} from "@/lib/realtime-refresh";
|
||||
|
||||
const cleanups: Array<() => void> = [];
|
||||
|
||||
afterEach(() => {
|
||||
for (const clean of cleanups.splice(0)) clean();
|
||||
});
|
||||
|
||||
function setup(
|
||||
filter: Parameters<typeof startRealtimeRefresh>[0]["filter"],
|
||||
debounceMs = 10,
|
||||
) {
|
||||
let handlers: RealtimeRefreshHandlers | undefined;
|
||||
const refresh = mock(() => {});
|
||||
const cleanSubscription = mock(() => {});
|
||||
const clean = startRealtimeRefresh({
|
||||
filter,
|
||||
debounceMs,
|
||||
refresh,
|
||||
subscribe(nextHandlers) {
|
||||
handlers = nextHandlers;
|
||||
return { clean: cleanSubscription };
|
||||
},
|
||||
});
|
||||
cleanups.push(clean);
|
||||
return {
|
||||
get handlers() {
|
||||
if (!handlers) throw new Error("Handlers were not registered.");
|
||||
return handlers;
|
||||
},
|
||||
refresh,
|
||||
clean,
|
||||
cleanSubscription,
|
||||
};
|
||||
}
|
||||
|
||||
describe("leaderboard realtime refresh", () => {
|
||||
test("filters XP and VC events by leaderboard scope", async () => {
|
||||
const xp = setup({ kind: "xp" });
|
||||
xp.handlers.onVc({ channelId: "1" });
|
||||
xp.handlers.onXp();
|
||||
await Bun.sleep(20);
|
||||
expect(xp.refresh).toHaveBeenCalledTimes(1);
|
||||
|
||||
const selectedVc = setup({ kind: "vc", channelId: "2" });
|
||||
selectedVc.handlers.onVc({ channelId: "1" });
|
||||
await Bun.sleep(20);
|
||||
expect(selectedVc.refresh).not.toHaveBeenCalled();
|
||||
selectedVc.handlers.onVc({ channelId: "2" });
|
||||
await Bun.sleep(20);
|
||||
expect(selectedVc.refresh).toHaveBeenCalledTimes(1);
|
||||
|
||||
const allVc = setup({ kind: "vc" });
|
||||
allVc.handlers.onVc({ channelId: "any" });
|
||||
await Bun.sleep(20);
|
||||
expect(allVc.refresh).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("refreshes after reconnect but not the initial connection", async () => {
|
||||
const subscription = setup({ kind: "xp" });
|
||||
subscription.handlers.onOpen();
|
||||
await Bun.sleep(20);
|
||||
expect(subscription.refresh).not.toHaveBeenCalled();
|
||||
|
||||
subscription.handlers.onOpen();
|
||||
await Bun.sleep(20);
|
||||
expect(subscription.refresh).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("debounces event bursts and cleans timers and subscriptions", async () => {
|
||||
const subscription = setup({ kind: "xp" }, 20);
|
||||
subscription.handlers.onXp();
|
||||
subscription.handlers.onXp();
|
||||
subscription.handlers.onXp();
|
||||
await Bun.sleep(30);
|
||||
expect(subscription.refresh).toHaveBeenCalledTimes(1);
|
||||
|
||||
subscription.handlers.onXp();
|
||||
subscription.clean();
|
||||
await Bun.sleep(30);
|
||||
expect(subscription.refresh).toHaveBeenCalledTimes(1);
|
||||
expect(subscription.cleanSubscription).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user