← back to Kickbacks Ai Upstream
test/earningsRefresh.test.ts
135 lines
// audit-2026-06-09 #34 regression: showActive used to flip authHealthy to
// "401" on ANY earnings-fetch failure (network blip, 5xx, malformed body),
// so the debug menu falsely showed "Sign in again — your session expired"
// during every offline poll. Only a REAL backend 401 may raise that signal;
// transient failures must leave the last verdict in place. Also pins the
// second half of the finding: a token that dies DURING the fetch paints
// signed-out, not a stale green "active" bar.
import { describe, it, expect, vi } from "vitest";
import type { AuthClient } from "../src/auth/client";
import { setupEarningsRefresh } from "../src/activation/earningsRefresh";
import { EarningsClient } from "../src/earnings/client";
import { SessionState } from "../src/sessionState";
import { makeContext } from "./mocks/vscode";
// Wires a real EarningsClient + SessionState behind setupEarningsRefresh.
// Token starts null so the constructor's `void showActive()` takes the
// signed-out path and the tests drive exactly ONE deterministic run each.
function wire(f: typeof fetch) {
let tok: string | null = null;
const session = new SessionState();
const statusBar = { set: vi.fn() };
const capWarning = { show: vi.fn(), hide: vi.fn() };
const auth = { accessToken: () => tok } as unknown as AuthClient;
const client = new EarningsClient("http://x", () => tok, f);
const { showActive } = setupEarningsRefresh(
auth, client, session, statusBar, "2.1.143", makeContext() as never,
undefined, capWarning);
return { session, statusBar, capWarning, showActive,
setToken: (t: string | null) => { tok = t; } };
}
const okFetch = (async () => ({
ok: true,
json: async () => ({ lifetime_usd: "1.20", today_usd: "0.04" }),
})) as unknown as typeof fetch;
describe("setupEarningsRefresh authHealthy (audit #34)", () => {
it("a 5xx does NOT set authHealthy '401'", async () => {
const f = (async () => ({ ok: false, status: 500 })) as unknown as typeof fetch;
const { session, showActive, setToken } = wire(f);
setToken("tok");
await showActive();
expect(session.get().signedIn).toBe(true);
expect(session.get().authHealthy).not.toBe("401");
});
it("a network error does NOT clobber a previously-ok verdict", async () => {
let mode: "ok" | "throw" = "ok";
const f = (async () => {
if (mode === "throw") throw new Error("offline");
return { ok: true,
json: async () => ({ lifetime_usd: "1.20", today_usd: "0.04" }) };
}) as unknown as typeof fetch;
const { session, showActive, setToken } = wire(f);
setToken("tok");
await showActive();
expect(session.get().authHealthy).toBe("ok");
mode = "throw"; // laptop loses connectivity
await showActive();
expect(session.get().authHealthy).toBe("ok"); // pre-fix: "401"
expect(session.get().signedIn).toBe(true);
});
it("a REAL backend 401 still sets authHealthy '401'", async () => {
const f = (async () => ({ ok: false, status: 401 })) as unknown as typeof fetch;
const { session, showActive, setToken } = wire(f);
setToken("tok");
await showActive();
expect(session.get().signedIn).toBe(true);
expect(session.get().authHealthy).toBe("401");
});
it("token death mid-fetch paints signed-out, not the green active bar", async () => {
let kill: (() => void) | null = null;
const f = (async () => {
kill?.(); // sign-out lands during the await
return { ok: true,
json: async () => ({ lifetime_usd: "1.20", today_usd: "0.04" }) };
}) as unknown as typeof fetch;
const { session, statusBar, showActive, setToken } = wire(f);
setToken("tok");
kill = () => setToken(null);
await showActive();
const last = statusBar.set.mock.calls.at(-1)?.[0] as { kind: string };
expect(last.kind).toBe("signed-out"); // pre-fix: "active"
expect(session.get().signedIn).toBe(false);
});
it("healthy fetch paints active with the fresh figures", async () => {
const { session, statusBar, showActive, setToken } = wire(okFetch);
setToken("tok");
await showActive();
expect(session.get().authHealthy).toBe("ok");
const last = statusBar.set.mock.calls.at(-1)?.[0] as
{ kind: string; usd?: string; usdToday?: string };
expect(last).toEqual({ kind: "active", version: "2.1.143",
usd: "1.20", usdToday: "0.04" });
});
});
describe("setupEarningsRefresh cap-warning pill", () => {
const cappedFetch = (async () => ({
ok: true,
json: async () => ({
lifetime_usd: "84.10", today_usd: "50.00",
cap: { scope: "daily", cap_usd: "50.00", reset_seconds: 22320 },
}),
})) as unknown as typeof fetch;
it("shows the pill when the earnings response carries a cap", async () => {
const { capWarning, showActive, setToken } = wire(cappedFetch);
setToken("tok");
await showActive();
expect(capWarning.show).toHaveBeenCalledWith(
{ scope: "daily", capUsd: "50.00", resetSeconds: 22320 });
expect(capWarning.hide).not.toHaveBeenCalled();
});
it("hides the pill when under both ceilings (no cap field)", async () => {
const { capWarning, showActive, setToken } = wire(okFetch);
setToken("tok");
await showActive();
expect(capWarning.hide).toHaveBeenCalled();
expect(capWarning.show).not.toHaveBeenCalled();
});
it("hides the pill on a not-earning safety state (signed-out)", async () => {
// Token null → the signed-out early-return must hide the pill.
const { capWarning, showActive } = wire(okFetch);
await showActive();
expect(capWarning.hide).toHaveBeenCalled();
expect(capWarning.show).not.toHaveBeenCalled();
});
});