Files
dsh-context/tests/client/overview.rows.spec.ts
T
bowenliang123 9aaa11591a test(client): split the oversized specs into siblings with shared harnesses
browser.spec.ts (2360), trendChart.spec.ts (1629), contextView.spec.ts (1504), and
overview.spec.ts (1065) exceeded the 1000-line limit. Each splits along its existing
describe seams into same-directory siblings, with the fixtures that more than one
sibling needs extracted once into a shared harness.

The move is verbatim: test titles, describe blocks, and every assertion line are
preserved exactly (2061 tests before and after, no duplicate titles, no skips), and
the suite reports the same coverage.
2026-10-10 01:21:15 +08:00

262 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from 'node:assert/strict'
import { describe, test } from 'vitest'
import { billedOf, rowsOfSnapshot, sessionsSnapshotOf, tokenPartsOf } from '../../src/client/overview'
import { mergeCostUsage } from '../../src/client/cost'
import type { SessionCostUsage } from '../../src/shared/types'
import { COST } from './overview.fixtures'
/** The minimal wire-valid timeline head, overridable per case. */
function timelineOf(over: Record<string, unknown> = {}): Record<string, unknown> {
return {
ok: true,
current: { system: 10, tools: 20, user: 30, inject: 5, skill: 5, assistant: 40, tool: 50, total: 160 },
requests: [],
events: [],
nodes: [],
droppedNodes: 0,
archive: [],
...over,
}
}
/** A session-list snapshot over rows of `{ id, row }` pairs. */
function snapshotOf(entries: [string, Record<string, unknown>][], current?: string): Record<string, unknown> {
return {
ids: entries.map(([id]) => id),
byId: Object.fromEntries(entries),
current,
phase: 'ready',
}
}
describe('sessionsSnapshotOf', () => {
test('a non-function seat reads null', () => {
assert.equal(sessionsSnapshotOf({}), null)
assert.equal(sessionsSnapshotOf({ useSessions: 7 }), null)
})
test('a throwing seat reads null instead of taking the render down', () => {
assert.equal(sessionsSnapshotOf({ useSessions: () => { throw new Error('boom') } }), null)
})
test('the raw snapshot passes through', () => {
const snap = { ids: [] }
assert.equal(sessionsSnapshotOf({ useSessions: (sel: (s: unknown) => unknown) => sel(snap) }), snap)
})
})
describe('rowsOfSnapshot', () => {
test('unusable snapshots read null (the unavailable note, not an empty list)', () => {
assert.equal(rowsOfSnapshot(null), null)
assert.equal(rowsOfSnapshot(7), null)
assert.equal(rowsOfSnapshot({}), null, 'ids missing')
assert.equal(rowsOfSnapshot({ ids: 'x' }), null, 'ids not an array')
})
test('an empty ready list reads as a real empty array', () => {
assert.deepEqual(rowsOfSnapshot({ ids: [], byId: {} }), [])
assert.deepEqual(rowsOfSnapshot({ ids: ['s1'] }), [], 'byId absent: the row is skipped')
assert.deepEqual(rowsOfSnapshot({ ids: [7, 's1'], byId: {} }), [], 'non-string ids drop')
})
test('blank rows drop; metadata derives on the display ladder', () => {
const rows = rowsOfSnapshot(snapshotOf([
['a', { blank: true, displayTitle: 'blank one' }],
['b', { displayTitle: 'shown', updatedAt: 5, running: true }],
['c', { title: 'titled' }],
['d', {}],
['e', { displayTitle: '', title: '', cwd: '/repo', updatedAt: 'x' }],
], 'b'))
assert.ok(rows !== null)
assert.equal(rows.length, 4)
const [b, c, d, e] = rows
assert.deepEqual(b, {
id: 'b', title: 'shown', updatedAt: 5, running: true, current: true,
timeline: null, activity: null, family: [null], familyCost: null,
})
assert.equal(c.title, 'titled')
assert.equal(c.current, false)
assert.equal(d.title, 'd', 'the id is the last-resort title')
assert.equal(e.title, 'e', 'empty strings fall through the ladder')
assert.equal(e.cwd, '/repo')
assert.equal(e.updatedAt, 0, 'a non-numeric stamp zeroes')
})
test('archived sessions drop; a hostile archive set fails open', () => {
const snap = snapshotOf([
['a', { displayTitle: 'live' }],
['b', { displayTitle: 'archived' }],
['c', { displayTitle: 'kept' }],
])
const rows = rowsOfSnapshot(snap, { archivedSessionIds: ['b', 7, null] })
assert.ok(rows !== null)
assert.deepEqual(rows.map(r => r.id), ['a', 'c'], 'archived ids drop; non-string entries archive nothing')
// Fail-open shapes: an absent seat, a bare record, a malformed set, and a throwing accessor all keep the full list.
assert.equal(rowsOfSnapshot(snap)?.length, 3)
assert.equal(rowsOfSnapshot(snap, null)?.length, 3)
assert.equal(rowsOfSnapshot(snap, 7)?.length, 3)
assert.equal(rowsOfSnapshot(snap, {})?.length, 3)
assert.equal(rowsOfSnapshot(snap, { archivedSessionIds: 'x' })?.length, 3)
assert.equal(rowsOfSnapshot(snap, { get archivedSessionIds() { throw new Error('boom') } })?.length, 3)
})
test('projection values are sanitized per row; hostile payloads degrade to nulls', () => {
const rows = rowsOfSnapshot(snapshotOf([
['a', {
displayTitle: 'good',
projectionValues: {
contextTimeline: timelineOf({ counts: { turns: 2, steps: 3, injects: 0, compactions: 0, prunes: 0 } }),
contextActivity: { days: { '2026-09-16': { tokens: 15, requests: 1 } } },
},
}],
['b', { displayTitle: 'junk', projectionValues: { contextTimeline: 7, contextActivity: 'x' } }],
]))
assert.ok(rows !== null)
const [a, b] = rows
assert.equal(a.timeline?.counts?.turns, 2)
assert.equal(a.activity?.days['2026-09-16'].tokens, 15)
assert.equal(b.timeline, null)
assert.equal(b.activity, null)
})
test('a hostile row that throws on access drops whole; the list survives', () => {
const hostile = new Proxy({}, { get: () => { throw new Error('boom') } })
const rows = rowsOfSnapshot({ ids: ['x', 'y'], byId: { x: hostile, y: { displayTitle: 'fine' } } })
assert.ok(rows !== null)
assert.equal(rows.length, 1)
assert.equal(rows[0].id, 'y')
})
})
describe('rowsOfSnapshot: subagent rows', () => {
test('subagent-origin rows drop out (the workspace browser’s own exclusion)', () => {
const rows = rowsOfSnapshot(snapshotOf([
['main', { displayTitle: 'main session' }],
['child', { displayTitle: 'subagent run', origin: 'subagent', parentId: 'main' }],
]))
assert.ok(rows !== null)
assert.deepEqual(rows.map(r => r.id), ['main'])
})
})
describe('rowsOfSnapshot: the family fold', () => {
const COST2: SessionCostUsage = { zhipuai: { m: { peak: { uncached: 300, cacheRead: 0, cacheWrite: 0, output: 0 } } } }
/** A minimal head carrying the given billed usage (and a user-only composition). */
function billedHead(tokens: number, cost?: SessionCostUsage): Record<string, unknown> {
return timelineOf({
current: { system: 0, tools: 0, user: tokens, inject: 0, skill: 0, assistant: 0, tool: 0, total: tokens },
...(cost !== undefined ? { cost } : {}),
})
}
test('every descendant level folds into the root row’s family — members, cost, and days merge', () => {
const rows = rowsOfSnapshot(snapshotOf([
['root', {
displayTitle: 'root',
projectionValues: {
contextTimeline: billedHead(100, COST),
contextActivity: { days: { '2026-09-16': { tokens: 5, requests: 1, cost: COST } } },
},
}],
['kid', {
origin: 'subagent', parentId: 'root',
projectionValues: {
contextTimeline: billedHead(50, COST2),
contextActivity: { days: { '2026-09-16': { tokens: 7, requests: 2, cost: COST2 } } },
},
}],
['grand', {
origin: 'subagent', parentId: 'kid',
projectionValues: {
contextTimeline: billedHead(25),
contextActivity: { days: { '2026-09-16': { tokens: 4, requests: 1 }, '2026-09-15': { tokens: 3, requests: 1 } } },
},
}],
['stranger', { displayTitle: 'unrelated' }],
]))
assert.ok(rows !== null)
assert.deepEqual(rows.map(r => r.id), ['root', 'stranger'], 'subagent-origin rows stay unlisted')
const [root, stranger] = rows
assert.equal(root.family.length, 3, 'self + kid + grand — all levels')
// COST (200) + COST2 (300) merge; the grandchild carried no cost.
assert.equal(billedOf(root), 500)
assert.equal(billedOf(stranger), null)
// The daily ledgers merge across the subtree, pricing records included.
assert.equal(root.activity?.days['2026-09-16'].tokens, 16)
assert.equal(root.activity?.days['2026-09-16'].requests, 4)
assert.deepEqual(root.activity?.days['2026-09-16'].cost, mergeCostUsage(COST, COST2))
assert.equal(root.activity?.days['2026-09-15'].tokens, 3)
assert.equal(root.activity?.days['2026-09-15'].cost, undefined)
// The composed split proportions each member's OWN composition: the root's
// all-user 160 billed input + output 40, the kid's all-user 300 — user 460 / output 40.
const parts = tokenPartsOf([root])
assert.deepEqual(parts, {
total: 500,
parts: [
{ key: 'user', color: 'var(--color-green-500)', value: 460 },
{ key: 'output', color: 'var(--color-pink-500)', value: 40 },
],
})
})
test('an unlisted subtree (a subagent whose root never lists) leaks nowhere', () => {
const rows = rowsOfSnapshot(snapshotOf([
['root', { displayTitle: 'root', projectionValues: { contextTimeline: billedHead(1, COST) } }],
['ghost', { origin: 'subagent', parentId: 'missing', projectionValues: { contextTimeline: billedHead(999, COST2) } }],
]))
assert.ok(rows !== null)
assert.equal(rows.length, 1)
assert.equal(billedOf(rows[0]), 200, 'the ghost subtree folds into no row')
})
test('a blank placeholder’s subtree stays out, and a lineage cycle cannot loop the walk', () => {
const rows = rowsOfSnapshot(snapshotOf([
// The reachable cycle: root points at p and p points back — the walk
// must cut at the revisited id (root counts its family, never itself twice).
['root', { displayTitle: 'root', parentId: 'p', projectionValues: { contextTimeline: billedHead(1, COST) } }],
['p', { origin: 'subagent', parentId: 'root', projectionValues: { contextTimeline: billedHead(2, COST2) } }],
['blank', { blank: true, parentId: 'root', projectionValues: { contextTimeline: billedHead(9, COST2) } }],
['under-blank', { origin: 'subagent', parentId: 'blank', projectionValues: { contextTimeline: billedHead(9, COST2) } }],
]))
assert.ok(rows !== null)
assert.equal(rows.length, 1)
assert.equal(rows[0].family.length, 2, 'root + p once; the blank is no agent and its child never links through')
assert.equal(billedOf(rows[0]), 500, 'COST + COST2 — the cycle’s revisit adds nothing twice')
})
test('the daily ledgers’ skill tables merge name by name (loads sum, last takes the max)', () => {
const rows = rowsOfSnapshot(snapshotOf([
['root', {
displayTitle: 'root',
projectionValues: {
contextActivity: { days: { '2026-09-16': { tokens: 5, requests: 1, skills: { tdd: { n: 2, last: 100 }, solo: { n: 1, last: 90 } } } } },
},
}],
['kid', {
origin: 'subagent', parentId: 'root',
projectionValues: {
contextActivity: { days: { '2026-09-16': { tokens: 7, requests: 2, skills: { tdd: { n: 3, last: 200 }, fresh: { n: 1, last: 300 } } } } },
},
}],
]))
assert.ok(rows !== null)
assert.deepEqual(rows[0].activity?.days['2026-09-16'].skills, {
tdd: { n: 5, last: 200 },
solo: { n: 1, last: 90 },
fresh: { n: 1, last: 300 },
})
})
test('hostile descendant projections degrade to null members, never a throw', () => { const rows = rowsOfSnapshot(snapshotOf([
['root', { displayTitle: 'root', projectionValues: { contextTimeline: billedHead(1, COST) } }],
['kid', { origin: 'subagent', parentId: 'root', projectionValues: { contextTimeline: 7, contextActivity: 'x' } }],
['junk', 5 as unknown as Record<string, unknown>],
]))
assert.ok(rows !== null)
assert.equal(rows[0].family.length, 2)
assert.equal(rows[0].family[1], null, 'the hostile head sanitizes to null in place')
assert.equal(rows[0].activity, null, 'no member carried a ledger → the family has none')
assert.equal(billedOf(rows[0]), 200)
})
})