diff --git a/src/app/actions/usage.test.ts b/src/app/actions/usage.test.ts index 604f6c3b..066f9f05 100644 --- a/src/app/actions/usage.test.ts +++ b/src/app/actions/usage.test.ts @@ -91,6 +91,34 @@ describe('getUsage', () => { }); }); + it('uses the current UTC calendar week (Monday 00:00) as the week window', async () => { + mocks.mockGetUser.mockResolvedValue({ data: { user: { id: 'user-1' } }, error: null }); + mocks.mockRateLimit.mockResolvedValue({ ok: true }); + + const logChain = makeChain(); + logChain.limit = vi.fn().mockResolvedValue({ data: [], error: null }); + + const todayChain = makeChain(); + todayChain.gte = vi.fn().mockResolvedValue({ data: [], error: null }); + + const weekChain = makeChain(); + const weekGte = vi.fn().mockResolvedValue({ data: [], error: null }); + weekChain.gte = weekGte; + + mocks.mockServiceFrom + .mockReturnValueOnce(logChain) + .mockReturnValueOnce(todayChain) + .mockReturnValueOnce(weekChain); + + await getUsage(); + + const weekBoundary = weekGte.mock.calls[0]?.[1] as string; + const boundary = new Date(weekBoundary); + expect(boundary.getUTCDay()).toBe(1); // Monday (UTC) + expect(weekBoundary).toMatch(/T00:00:00.000Z$/); // start of a calendar day + expect(boundary.getTime()).toBeLessThanOrEqual(Date.now()); + }); + it('respects limit parameter', async () => { mocks.mockGetUser.mockResolvedValue({ data: { user: { id: 'user-1' } }, error: null }); mocks.mockRateLimit.mockResolvedValue({ ok: true }); diff --git a/src/app/actions/usage.ts b/src/app/actions/usage.ts index b47f0b4d..f303c5d5 100644 --- a/src/app/actions/usage.ts +++ b/src/app/actions/usage.ts @@ -41,8 +41,16 @@ export async function getUsage(limit = 100): Promise { const service = getServiceSupabase(); if (!service) return empty; - const dayStart = new Date(new Date().toISOString().slice(0, 10) + 'T00:00:00Z').toISOString(); - const weekStart = new Date(Date.now() - 7 * 24 * 3600 * 1000).toISOString(); + // Calendar-aligned windows. dayStart = today 00:00 UTC; weekStart = the + // current UTC calendar week's Monday 00:00 (same date_trunc('week') + // boundaries the maintainer analytics use), so the week total is stable + // within a day and comparable to the weekly chart. + const now = new Date(); + const dayStart = new Date(now.toISOString().slice(0, 10) + 'T00:00:00Z').toISOString(); + const daysSinceMonday = (now.getUTCDay() + 6) % 7; // 0 = Sunday + const weekStart = new Date( + Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() - daysSinceMonday), + ).toISOString(); const [logRes, todayRes, weekRes] = await Promise.all([ service