fix(dashboard): Bound Daily Activity scans (#727)

Reuse one concrete six-month scan for interactive history and selected-period totals. This restores network-backed providers, removes concurrent refresh scans, and keeps non-interactive reports scoped to their requested period.
This commit is contained in:
ihearttokyo 2026-07-20 21:21:35 +09:00 committed by GitHub
parent 7f2739e130
commit 92b2b5ef39
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 65 additions and 45 deletions

View file

@ -2,7 +2,8 @@ import { homedir } from 'os'
import { describe, it, expect } from 'vitest'
import { getDailyActivityRows, pageHistoryCursor, scrollHistoryCursor, shortProject, showEmptyState } from '../src/dashboard.js'
import { getDailyActivityRows, getDashboardScanRange, pageHistoryCursor, scrollHistoryCursor, selectDashboardPeriodProjects, shortProject, showEmptyState } from '../src/dashboard.js'
import { getDateRange } from '../src/cli-date.js'
import { formatCost } from '../src/format.js'
import type { ProjectSummary, SessionSummary } from '../src/types.js'
@ -173,6 +174,35 @@ describe('avg/s in ProjectBreakdown', () => {
})
describe('Daily Activity history', () => {
it('uses one concrete six-month scan for standard dashboard periods', () => {
const scanRange = getDashboardScanRange('week', null, null)
const allRange = getDateRange('all').range
expect(scanRange.start.getTime()).toBe(allRange.start.getTime())
expect(scanRange.end.getTime()).toBe(allRange.end.getTime())
})
it('keeps non-interactive output scoped to the selected period', () => {
const scanRange = getDashboardScanRange('week', null, null, false)
const weekRange = getDateRange('week').range
expect(scanRange.start.getTime()).toBe(weekRange.start.getTime())
expect(scanRange.end.getTime()).toBe(weekRange.end.getTime())
})
it('derives the selected period from the bounded history scan', () => {
const recent = new Date().toISOString()
const old = new Date()
old.setMonth(old.getMonth() - 2)
const session = makeSession('s1', 0)
session.turns = [makeTurn(old.toISOString(), [1]), makeTurn(recent, [2])]
const selected = selectDashboardPeriodProjects([makeProject('proj', [session])], 'week', true)
expect(getDailyActivityRows(selected)).toEqual([
{ day: recent.slice(0, 10), cost: 2, calls: 1 },
])
})
it('aggregates every active day in chronological order', () => {
const session = makeSession('s1', 0)
session.turns = [

View file

@ -4,6 +4,7 @@ import { tmpdir } from 'os'
import { join } from 'path'
import { fetchVercelGatewayReport, vercelGateway } from '../../src/providers/vercel-gateway.js'
import { parseAllSessions, clearSessionCache } from '../../src/parser.js'
import { getDashboardScanRange } from '../../src/dashboard.js'
describe('vercel-gateway provider', () => {
const originalFetch = globalThis.fetch
@ -105,10 +106,7 @@ describe('vercel-gateway end-to-end (parseAllSessions network path)', () => {
}),
})) as typeof fetch
const range = {
start: new Date('2026-05-01T00:00:00.000Z'),
end: new Date('2026-06-09T23:59:59.999Z'),
}
const range = getDashboardScanRange('week', null, null)
const projects = await parseAllSessions(range, 'vercel-gateway')
const total = projects.reduce((sum, p) => sum + p.totalCostUSD, 0)