test(frontend): add ActivityFeed component tests + expand coverage slice

This commit is contained in:
Anya
2026-02-07 16:52:56 +00:00
parent 64581f4534
commit 15bc7ae833
5 changed files with 189 additions and 63 deletions

View File

@@ -1,61 +1,67 @@
import { describe, expect, it, vi } from "vitest";
import { createExponentialBackoff } from "./backoff";
describe("createExponentialBackoff", () => {
it("increments attempt and clamps delay", () => {
vi.spyOn(Math, "random").mockReturnValue(0);
it("uses default options", () => {
const backoff = createExponentialBackoff();
expect(backoff.attempt()).toBe(0);
const delay = backoff.nextDelayMs();
expect(delay).toBeGreaterThanOrEqual(50);
expect(backoff.attempt()).toBe(1);
});
it("clamps invalid base/max and increments attempt", () => {
const backoff = createExponentialBackoff({
baseMs: 100,
baseMs: Number.NaN,
maxMs: Number.POSITIVE_INFINITY,
factor: 2,
maxMs: 250,
jitter: 0,
});
expect(backoff.attempt()).toBe(0);
expect(backoff.nextDelayMs()).toBe(100);
const d1 = backoff.nextDelayMs();
// baseMs clamps to min 50
expect(d1).toBe(50);
expect(backoff.attempt()).toBe(1);
expect(backoff.nextDelayMs()).toBe(200);
expect(backoff.nextDelayMs()).toBe(250); // capped
});
it("clamps invalid numeric options and treats negative jitter as zero", () => {
vi.spyOn(Math, "random").mockReturnValue(0.9999);
// baseMs: NaN should clamp to min (50)
// maxMs: Infinity should clamp to min (= baseMs)
// jitter: negative -> treated as 0 (no extra delay)
const backoff = createExponentialBackoff({
baseMs: Number.NaN,
maxMs: Number.POSITIVE_INFINITY,
jitter: -1,
});
// With maxMs clamped to baseMs, delay will always be baseMs
expect(backoff.nextDelayMs()).toBe(50);
expect(backoff.nextDelayMs()).toBe(50);
});
it("reset brings attempt back to zero", () => {
vi.spyOn(Math, "random").mockReturnValue(0);
const backoff = createExponentialBackoff({ baseMs: 100, jitter: 0 });
backoff.nextDelayMs();
expect(backoff.attempt()).toBe(1);
const d2 = backoff.nextDelayMs();
// maxMs=+Inf is treated as invalid and clamped to baseMs, so it will cap immediately.
expect(d2).toBe(50);
expect(backoff.attempt()).toBe(2);
backoff.reset();
expect(backoff.attempt()).toBe(0);
});
it("uses defaults when options are omitted", () => {
vi.spyOn(Math, "random").mockReturnValue(0);
it("applies positive jitter (extra delay only)", () => {
const randomSpy = vi.spyOn(Math, "random").mockReturnValue(0.5);
const backoff = createExponentialBackoff();
expect(backoff.attempt()).toBe(0);
const backoff = createExponentialBackoff({
baseMs: 1000,
factor: 2,
maxMs: 2000,
jitter: 0.2,
});
// Default baseMs is 1000 (clamped within bounds), jitter default is 0.2.
// With Math.random=0, delay should be the normalized base (1000).
expect(backoff.nextDelayMs()).toBe(1000);
// attempt=0 => normalized=1000 => delay = 1000 + floor(0.5*0.2*1000)=1100
expect(backoff.nextDelayMs()).toBe(1100);
// attempt=1 => raw=2000 capped=2000 => delay=2000 + floor(0.5*0.2*2000)=2200 but clamped to maxMs (2000)
expect(backoff.nextDelayMs()).toBe(2000);
randomSpy.mockRestore();
});
it("treats negative jitter as zero", () => {
const randomSpy = vi.spyOn(Math, "random").mockReturnValue(0.999);
const backoff = createExponentialBackoff({
baseMs: 100,
factor: 2,
maxMs: 1000,
jitter: -1,
});
expect(backoff.nextDelayMs()).toBe(100);
randomSpy.mockRestore();
});
});