feat(FN-1176): synthesize fallback resetAt for Claude usage windows
- Update Claude usage window normalization to set resetAt when API omits reset timestamps - Derive fallback resetAt as now plus the computed window duration while preserving existing resetMs/resetText behavior - Expand usage tests to assert fallback resetAt is present and approximately 5 hours in the future in both affected scenarios
This commit is contained in:
@@ -790,7 +790,10 @@ describe("usage", () => {
|
|||||||
|
|
||||||
expect(claude.status).toBe("ok");
|
expect(claude.status).toBe("ok");
|
||||||
const sessionWindow = claude.windows.find((w) => w.label.includes("Session"))!;
|
const sessionWindow = claude.windows.find((w) => w.label.includes("Session"))!;
|
||||||
expect(sessionWindow.resetAt).toBeUndefined();
|
expect(sessionWindow.resetAt).toBeDefined();
|
||||||
|
const resetAtDate = new Date(sessionWindow.resetAt!);
|
||||||
|
const expectedMs = Date.now() + 5 * 60 * 60 * 1000;
|
||||||
|
expect(Math.abs(resetAtDate.getTime() - expectedMs)).toBeLessThan(1000);
|
||||||
// Fallback: when resets_at is missing, session window gets resetMs = 5h
|
// Fallback: when resets_at is missing, session window gets resetMs = 5h
|
||||||
expect(sessionWindow.resetMs).toBe(5 * 60 * 60 * 1000);
|
expect(sessionWindow.resetMs).toBe(5 * 60 * 60 * 1000);
|
||||||
expect(sessionWindow.resetText).toBe("resets in 5h");
|
expect(sessionWindow.resetText).toBe("resets in 5h");
|
||||||
@@ -823,8 +826,10 @@ describe("usage", () => {
|
|||||||
expect(sessionWindow.windowDurationMs).toBe(5 * 60 * 60 * 1000);
|
expect(sessionWindow.windowDurationMs).toBe(5 * 60 * 60 * 1000);
|
||||||
expect(sessionWindow.resetMs).toBe(5 * 60 * 60 * 1000);
|
expect(sessionWindow.resetMs).toBe(5 * 60 * 60 * 1000);
|
||||||
expect(sessionWindow.resetText).toBe("resets in 5h");
|
expect(sessionWindow.resetText).toBe("resets in 5h");
|
||||||
// resetAt stays undefined because the API didn't provide it
|
expect(sessionWindow.resetAt).toBeDefined();
|
||||||
expect(sessionWindow.resetAt).toBeUndefined();
|
const resetAtDate = new Date(sessionWindow.resetAt!);
|
||||||
|
const expectedMs = Date.now() + 5 * 60 * 60 * 1000;
|
||||||
|
expect(Math.abs(resetAtDate.getTime() - expectedMs)).toBeLessThan(1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("handles empty JSON object from API gracefully", async () => {
|
it("handles empty JSON object from API gracefully", async () => {
|
||||||
|
|||||||
@@ -837,7 +837,7 @@ async function fetchClaudeUsage(): Promise<ProviderUsage> {
|
|||||||
let resetText: string | null = null;
|
let resetText: string | null = null;
|
||||||
let resetMs: number | undefined;
|
let resetMs: number | undefined;
|
||||||
|
|
||||||
const resetAtValue = w.resets_at || w.reset_at || w.resetAt;
|
let resetAtValue = w.resets_at || w.reset_at || w.resetAt;
|
||||||
if (resetAtValue) {
|
if (resetAtValue) {
|
||||||
const msLeft = new Date(resetAtValue).getTime() - Date.now();
|
const msLeft = new Date(resetAtValue).getTime() - Date.now();
|
||||||
resetMs = msLeft > 0 ? msLeft : 0;
|
resetMs = msLeft > 0 ? msLeft : 0;
|
||||||
@@ -849,6 +849,7 @@ async function fetchClaudeUsage(): Promise<ProviderUsage> {
|
|||||||
// the API omits resets_at / reset_at / resetAt fields.
|
// the API omits resets_at / reset_at / resetAt fields.
|
||||||
resetMs = windowDurationMs;
|
resetMs = windowDurationMs;
|
||||||
resetText = "resets in 5h";
|
resetText = "resets in 5h";
|
||||||
|
resetAtValue = new Date(Date.now() + windowDurationMs).toISOString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user