refactor(runtime-tests): share typing lease assertions

This commit is contained in:
Peter Steinberger 2026-03-17 06:42:28 +00:00
parent 214c7a481c
commit 52ad686ab5
3 changed files with 84 additions and 71 deletions

View File

@ -1,5 +1,9 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, it, vi } from "vitest";
import { createDiscordTypingLease } from "./runtime-discord-typing.js";
import {
expectBackgroundTypingPulseFailuresAreSwallowed,
expectIndependentTypingLeases,
} from "./typing-lease.test-support.js";
describe("createDiscordTypingLease", () => {
afterEach(() => {
@ -7,51 +11,30 @@ describe("createDiscordTypingLease", () => {
});
it("pulses immediately and keeps leases independent", async () => {
vi.useFakeTimers();
const pulse = vi.fn(async () => undefined);
const leaseA = await createDiscordTypingLease({
channelId: "123",
intervalMs: 2_000,
pulse,
await expectIndependentTypingLeases({
createLease: createDiscordTypingLease,
buildParams: (pulse) => ({
channelId: "123",
intervalMs: 2_000,
pulse,
}),
});
const leaseB = await createDiscordTypingLease({
channelId: "123",
intervalMs: 2_000,
pulse,
});
expect(pulse).toHaveBeenCalledTimes(2);
await vi.advanceTimersByTimeAsync(2_000);
expect(pulse).toHaveBeenCalledTimes(4);
leaseA.stop();
await vi.advanceTimersByTimeAsync(2_000);
expect(pulse).toHaveBeenCalledTimes(5);
await leaseB.refresh();
expect(pulse).toHaveBeenCalledTimes(6);
leaseB.stop();
});
it("swallows background pulse failures", async () => {
vi.useFakeTimers();
const pulse = vi
.fn<(params: { channelId: string; accountId?: string; cfg?: unknown }) => Promise<void>>()
.mockResolvedValueOnce(undefined)
.mockRejectedValueOnce(new Error("boom"));
const lease = await createDiscordTypingLease({
channelId: "123",
intervalMs: 2_000,
await expectBackgroundTypingPulseFailuresAreSwallowed({
createLease: createDiscordTypingLease,
pulse,
buildParams: (pulse) => ({
channelId: "123",
intervalMs: 2_000,
pulse,
}),
});
await expect(vi.advanceTimersByTimeAsync(2_000)).resolves.toBe(vi);
expect(pulse).toHaveBeenCalledTimes(2);
lease.stop();
});
});

View File

@ -1,5 +1,9 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { createTelegramTypingLease } from "./runtime-telegram-typing.js";
import {
expectBackgroundTypingPulseFailuresAreSwallowed,
expectIndependentTypingLeases,
} from "./typing-lease.test-support.js";
describe("createTelegramTypingLease", () => {
afterEach(() => {
@ -7,37 +11,17 @@ describe("createTelegramTypingLease", () => {
});
it("pulses immediately and keeps leases independent", async () => {
vi.useFakeTimers();
const pulse = vi.fn(async () => undefined);
const leaseA = await createTelegramTypingLease({
to: "telegram:123",
intervalMs: 2_000,
pulse,
await expectIndependentTypingLeases({
createLease: createTelegramTypingLease,
buildParams: (pulse) => ({
to: "telegram:123",
intervalMs: 2_000,
pulse,
}),
});
const leaseB = await createTelegramTypingLease({
to: "telegram:123",
intervalMs: 2_000,
pulse,
});
expect(pulse).toHaveBeenCalledTimes(2);
await vi.advanceTimersByTimeAsync(2_000);
expect(pulse).toHaveBeenCalledTimes(4);
leaseA.stop();
await vi.advanceTimersByTimeAsync(2_000);
expect(pulse).toHaveBeenCalledTimes(5);
await leaseB.refresh();
expect(pulse).toHaveBeenCalledTimes(6);
leaseB.stop();
});
it("swallows background pulse failures", async () => {
vi.useFakeTimers();
const pulse = vi
.fn<
(params: {
@ -50,16 +34,15 @@ describe("createTelegramTypingLease", () => {
.mockResolvedValueOnce(undefined)
.mockRejectedValueOnce(new Error("boom"));
const lease = await createTelegramTypingLease({
to: "telegram:123",
intervalMs: 2_000,
await expectBackgroundTypingPulseFailuresAreSwallowed({
createLease: createTelegramTypingLease,
pulse,
buildParams: (pulse) => ({
to: "telegram:123",
intervalMs: 2_000,
pulse,
}),
});
await expect(vi.advanceTimersByTimeAsync(2_000)).resolves.toBe(vi);
expect(pulse).toHaveBeenCalledTimes(2);
lease.stop();
});
it("falls back to the default interval for non-finite values", async () => {

View File

@ -0,0 +1,47 @@
import { expect, vi } from "vitest";
export async function expectIndependentTypingLeases<
TParams extends { intervalMs?: number; pulse: (...args: never[]) => Promise<unknown> },
TLease extends { refresh: () => Promise<void>; stop: () => void },
>(params: {
createLease: (params: TParams) => Promise<TLease>;
buildParams: (pulse: TParams["pulse"]) => TParams;
}) {
vi.useFakeTimers();
const pulse = vi.fn(async () => undefined) as TParams["pulse"];
const leaseA = await params.createLease(params.buildParams(pulse));
const leaseB = await params.createLease(params.buildParams(pulse));
expect(pulse).toHaveBeenCalledTimes(2);
await vi.advanceTimersByTimeAsync(2_000);
expect(pulse).toHaveBeenCalledTimes(4);
leaseA.stop();
await vi.advanceTimersByTimeAsync(2_000);
expect(pulse).toHaveBeenCalledTimes(5);
await leaseB.refresh();
expect(pulse).toHaveBeenCalledTimes(6);
leaseB.stop();
}
export async function expectBackgroundTypingPulseFailuresAreSwallowed<
TParams extends { intervalMs?: number; pulse: (...args: never[]) => Promise<unknown> },
TLease extends { stop: () => void },
>(params: {
createLease: (params: TParams) => Promise<TLease>;
buildParams: (pulse: TParams["pulse"]) => TParams;
pulse: TParams["pulse"];
}) {
vi.useFakeTimers();
const lease = await params.createLease(params.buildParams(params.pulse));
await expect(vi.advanceTimersByTimeAsync(2_000)).resolves.toBe(vi);
expect(params.pulse).toHaveBeenCalledTimes(2);
lease.stop();
}