Files
oh-my-pi/packages/coding-agent/test/status-line-usage-refresh.test.ts
T
roboomp 31122d2409 fix(coding-agent): timeboxed status usage refresh
Deferred the status-line quota refresh off the render path and raced it against a short startup timeout so slow Anthropic usage lookups cannot pin interactive startup. Added regression coverage for non-synchronous refresh startup and timeout backoff.\n\nFixes #3057
2026-06-19 17:06:47 +00:00

88 lines
2.2 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from "bun:test";
import { resetSettingsForTest, Settings } from "@oh-my-pi/pi-coding-agent/config/settings";
import { StatusLineComponent } from "@oh-my-pi/pi-coding-agent/modes/components/status-line";
import type { AgentSession } from "@oh-my-pi/pi-coding-agent/session/agent-session";
async function flushMicrotasks(): Promise<void> {
await Promise.resolve();
await Promise.resolve();
}
function makeSession(fetchUsageReports: (signal?: AbortSignal) => Promise<unknown>): AgentSession {
return { fetchUsageReports } as unknown as AgentSession;
}
describe("StatusLineComponent usage refresh", () => {
beforeEach(async () => {
resetSettingsForTest();
await Settings.init({ inMemory: true });
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
resetSettingsForTest();
});
it("does not invoke usage fetching synchronously on the render path", async () => {
let calls = 0;
const component = new StatusLineComponent(
makeSession(async () => {
calls++;
return [];
}),
);
component.refreshUsageInBackground();
expect(calls).toBe(0);
vi.advanceTimersByTime(0);
await flushMicrotasks();
expect(calls).toBe(1);
});
it("passes a startup timeout signal to the background usage fetch", async () => {
let signal: AbortSignal | undefined;
const component = new StatusLineComponent(
makeSession(async nextSignal => {
signal = nextSignal;
return [];
}),
);
component.refreshUsageInBackground();
vi.advanceTimersByTime(0);
await flushMicrotasks();
expect(signal).toBeInstanceOf(AbortSignal);
});
it("backs off after the startup timeout when usage fetching hangs", async () => {
let calls = 0;
const component = new StatusLineComponent(
makeSession(() => {
calls++;
return Promise.withResolvers<unknown>().promise;
}),
);
component.refreshUsageInBackground();
vi.advanceTimersByTime(0);
await flushMicrotasks();
expect(calls).toBe(1);
component.refreshUsageInBackground();
expect(calls).toBe(1);
vi.advanceTimersByTime(2_000);
await flushMicrotasks();
component.refreshUsageInBackground();
vi.advanceTimersByTime(0);
await flushMicrotasks();
expect(calls).toBe(1);
});
});