test(desktop): trim context-gauge tests to two lifecycle invariants (#70871)
Drop the resolveContextGaugeUsage unit file and three lifecycle cases; keep the end-to-end contracts: streamed usage drives the gauge mid-turn and at turn end until a fresh idle breakdown lands, and a failed idle refresh never restores the pre-turn snapshot. Co-authored-by: konsisumer <11262660+konsisumer@users.noreply.github.com> Co-authored-by: webtecnica <75556242+webtecnica@users.noreply.github.com>
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import type { ContextBreakdown, UsageStats } from '@/types/hermes'
|
||||
|
||||
import { resolveContextGaugeUsage } from './use-statusbar-items'
|
||||
|
||||
// Regression for #70871's frozen-gauge half: while a turn is streaming the
|
||||
// pre-turn context breakdown must NOT overlay the live streamed usage —
|
||||
// otherwise the bar stays frozen at the turn-start value and jumps at turn end.
|
||||
const CURRENT: UsageStats = {
|
||||
calls: 1,
|
||||
context_estimated: true,
|
||||
context_source: 'provider_usage_plus_estimate',
|
||||
context_max: 1_000_000,
|
||||
context_percent: 27,
|
||||
context_used: 267_700,
|
||||
input: 10_000,
|
||||
output: 5_000,
|
||||
total: 15_000
|
||||
}
|
||||
|
||||
const BREAKDOWN: ContextBreakdown = {
|
||||
categories: [],
|
||||
context_estimated: false,
|
||||
context_source: 'provider_usage',
|
||||
context_max: 1_000_000,
|
||||
context_percent: 30,
|
||||
context_used: 320_000,
|
||||
estimated_total: 350_000,
|
||||
model: 'test-model'
|
||||
}
|
||||
|
||||
describe('resolveContextGaugeUsage', () => {
|
||||
it('keeps the live streamed usage mid-turn even when a breakdown is held', () => {
|
||||
const out = resolveContextGaugeUsage({ busy: true, breakdown: BREAKDOWN, current: CURRENT })
|
||||
|
||||
expect(out.context_used).toBe(267_700)
|
||||
expect(out.context_percent).toBe(27)
|
||||
expect(out.input).toBe(10_000)
|
||||
expect(out.context_estimated).toBe(true)
|
||||
expect(out.context_source).toBe('provider_usage_plus_estimate')
|
||||
})
|
||||
|
||||
it('falls back to the streamed usage mid-turn when no breakdown is held', () => {
|
||||
const out = resolveContextGaugeUsage({ busy: true, breakdown: null, current: CURRENT })
|
||||
|
||||
expect(out).toBe(CURRENT)
|
||||
})
|
||||
|
||||
it('lets the breakdown win when the turn is idle', () => {
|
||||
const out = resolveContextGaugeUsage({ busy: false, breakdown: BREAKDOWN, current: CURRENT })
|
||||
|
||||
expect(out.context_used).toBe(320_000)
|
||||
expect(out.context_percent).toBe(30)
|
||||
expect(out.context_max).toBe(1_000_000)
|
||||
// Non-context fields still come from the streamed usage object.
|
||||
expect(out.input).toBe(10_000)
|
||||
expect(out.calls).toBe(1)
|
||||
expect(out.context_estimated).toBe(false)
|
||||
expect(out.context_source).toBe('provider_usage')
|
||||
})
|
||||
|
||||
it('keeps the streamed usage when idle without a breakdown', () => {
|
||||
const out = resolveContextGaugeUsage({ busy: false, breakdown: undefined, current: CURRENT })
|
||||
|
||||
expect(out).toBe(CURRENT)
|
||||
})
|
||||
})
|
||||
@@ -133,46 +133,4 @@ describe('statusbar context usage lifecycle', () => {
|
||||
await act(async () => pending[1].reject(new Error('disconnected')))
|
||||
expect(meter().label).toBe('40k/100k')
|
||||
})
|
||||
|
||||
it('ignores an idle RPC that resolves after a turn has started', async () => {
|
||||
const { meter, pending } = mountStatusbar()
|
||||
act(() => {
|
||||
$busy.set(true)
|
||||
$currentUsage.set(usage(40_000))
|
||||
})
|
||||
await act(async () => pending[0].resolve(breakdown(20_000)))
|
||||
expect(meter().label).toBe('40k/100k')
|
||||
act(() => $busy.set(false))
|
||||
expect(meter().label).toBe('40k/100k')
|
||||
})
|
||||
|
||||
it('does not accept the previous session RPC after switching sessions', async () => {
|
||||
const { meter, pending } = mountStatusbar()
|
||||
act(() => {
|
||||
$activeSessionId.set('runtime-b')
|
||||
$selectedStoredSessionId.set('stored-b')
|
||||
$currentUsage.set(usage(5_000))
|
||||
})
|
||||
expect(meter().label).toBe('5k/100k')
|
||||
await act(async () => pending[1].resolve(breakdown(8_000)))
|
||||
await act(async () => pending[0].resolve(breakdown(20_000)))
|
||||
expect(meter().label).toBe('8k/100k')
|
||||
})
|
||||
|
||||
it('waits to fetch until the gauge is enabled and skips fetching while busy', async () => {
|
||||
$statusbarHiddenIds.set(['context-usage'])
|
||||
const { meter, pending } = mountStatusbar()
|
||||
expect(pending).toHaveLength(0)
|
||||
act(() => {
|
||||
$busy.set(true)
|
||||
$statusbarHiddenIds.set([])
|
||||
$currentUsage.set(usage(30_000))
|
||||
})
|
||||
expect(meter().label).toBe('30k/100k')
|
||||
expect(pending).toHaveLength(0)
|
||||
act(() => $busy.set(false))
|
||||
expect(pending).toHaveLength(1)
|
||||
await act(async () => pending[0].resolve(breakdown(35_000)))
|
||||
expect(meter().label).toBe('35k/100k')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user