Files
prowler/ui/__tests__/browser-harness.integration.test.ts
T

84 lines
2.5 KiB
TypeScript

/**
* Covers only the polling contract of `BrowserHarness`, which every page
* harness inherits: a silent `null` where a predicate actually threw sends the
* caller hunting a phantom timeout. Lives in the browser project because the
* base class imports `vitest/browser`.
*/
import { describe, expect, it } from "vitest";
import { BrowserHarness } from "./browser-harness";
const QUIET_MS = 50;
/** Exposes the protected waiting helpers; no fixture or DOM is involved. */
class WaitingHarness extends BrowserHarness<null> {
constructor() {
super(null);
}
probe<T>(fn: () => T | null | undefined | false): Promise<T> {
return this.waitFor(fn, 200, "probe", 10);
}
probeOrNull<T>(fn: () => T | null | undefined | false): Promise<T | null> {
return this.waitForOrNull(fn, 200, "probe");
}
probeStable<T>(read: () => T): Promise<T> {
return this.waitForStable(read, QUIET_MS, 1000, "probe");
}
}
describe("BrowserHarness waiting helpers", () => {
it("resolves to null when the predicate only ever stays falsy", async () => {
const harness = new WaitingHarness();
await expect(harness.probeOrNull<string>(() => null)).resolves.toBeNull();
});
it("rejects with the predicate's error when it throws and then goes falsy", async () => {
const harness = new WaitingHarness();
const boom = new Error("predicate blew up");
let calls = 0;
// `vi.waitFor` polls past a throw and rejects with the *last* error, so the
// falsy polls would otherwise bury `boom` under the timeout sentinel.
await expect(
harness.probeOrNull<string>(() => {
calls += 1;
if (calls === 1) throw boom;
return null;
}),
).rejects.toBe(boom);
});
it("still polls through a transient throw", async () => {
const harness = new WaitingHarness();
let calls = 0;
await expect(
harness.probe(() => {
calls += 1;
if (calls === 1) throw new Error("transient");
return "ready";
}),
).resolves.toBe("ready");
});
it("resolves with a value only once it has held for the quiet window", async () => {
const harness = new WaitingHarness();
let reads = 0;
let settledAt = 0;
// Changes on each of the first reads, then holds at 4.
const settled = await harness.probeStable(() => {
reads += 1;
if (reads === 4) settledAt = performance.now();
return Math.min(reads, 4);
});
expect(settled).toBe(4);
expect(performance.now() - settledAt).toBeGreaterThanOrEqual(QUIET_MS);
});
});