codeburn/tests/cli-status-menubar.test.ts
iamtoruk 6a12d818d9 Sync package-lock.json to 0.9.9 and fix flaky menubar test
package-lock.json was stale at 0.9.7 with engines >=22; now matches
package.json 0.9.9 / >=22.13.0.

The menubar-json CLI test used hardcoded 10:00/11:00 UTC timestamps
which fall in the "future" when the test runs before those hours,
causing the menubar's todayRange (start..now) to exclude them.
Use timestamps relative to now instead.
2026-05-15 20:03:44 -07:00

108 lines
3.5 KiB
TypeScript

import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { spawnSync } from 'node:child_process'
import { describe, expect, it } from 'vitest'
function runCli(args: string[], home: string) {
return spawnSync(process.execPath, ['--import', 'tsx', 'src/cli.ts', ...args], {
cwd: process.cwd(),
env: {
...process.env,
CLAUDE_CONFIG_DIR: join(home, '.claude'),
HOME: home,
TZ: 'UTC',
},
encoding: 'utf-8',
timeout: 30_000,
})
}
function userLine(sessionId: string, timestamp: string): string {
return JSON.stringify({
type: 'user',
sessionId,
timestamp,
message: { role: 'user', content: 'do the thing' },
})
}
function assistantLine(sessionId: string, timestamp: string, messageId: string): string {
return JSON.stringify({
type: 'assistant',
sessionId,
timestamp,
message: {
id: messageId,
type: 'message',
role: 'assistant',
model: 'claude-sonnet-4-5',
content: [
{ type: 'text', text: 'done' },
{ type: 'tool_use', id: 'tu-1', name: 'Edit', input: { file_path: '/tmp/x', old_string: 'a', new_string: 'b' } },
],
usage: { input_tokens: 500, output_tokens: 50 },
},
})
}
describe('codeburn status --format menubar-json', () => {
it('returns valid MenubarPayload with expected top-level fields', async () => {
const home = await mkdtemp(join(tmpdir(), 'codeburn-menubar-'))
try {
const projectDir = join(home, '.claude', 'projects', 'myapp')
await mkdir(projectDir, { recursive: true })
const now = new Date()
const h = now.getUTCHours()
const base = h >= 2 ? new Date(now.getTime() - 2 * 3600_000) : new Date(now.getTime() - h * 3600_000 - 60_000)
const ts1 = base.toISOString().replace(/\.\d+Z$/, 'Z')
const ts2 = new Date(base.getTime() + 60_000).toISOString().replace(/\.\d+Z$/, 'Z')
const ts3 = new Date(base.getTime() + 120_000).toISOString().replace(/\.\d+Z$/, 'Z')
const ts4 = new Date(base.getTime() + 180_000).toISOString().replace(/\.\d+Z$/, 'Z')
await writeFile(
join(projectDir, 'session.jsonl'),
[
userLine('s1', ts1),
assistantLine('s1', ts2, 'msg-1'),
userLine('s1', ts3),
assistantLine('s1', ts4, 'msg-2'),
].join('\n'),
)
const result = runCli([
'status',
'--format', 'menubar-json',
'--period', 'today',
'--provider', 'all',
'--no-optimize',
], home)
expect(result.status, `stderr: ${result.stderr}`).toBe(0)
const payload = JSON.parse(result.stdout) as Record<string, unknown>
expect(payload).toHaveProperty('generated')
expect(payload).toHaveProperty('current')
expect(payload).toHaveProperty('optimize')
expect(payload).toHaveProperty('history')
const current = payload['current'] as Record<string, unknown>
expect(current['cost']).toBeGreaterThan(0)
expect(current['calls']).toBe(2)
expect(current['sessions']).toBe(1)
expect(current).toHaveProperty('oneShotRate')
expect(current).toHaveProperty('topActivities')
expect(current).toHaveProperty('topModels')
expect(current).toHaveProperty('providers')
const history = payload['history'] as { daily: unknown[] }
expect(Array.isArray(history.daily)).toBe(true)
} finally {
await rm(home, { recursive: true, force: true })
}
})
})