test: add computeSubtreeCost coverage (flat, nested, cycle, zero-cost, unknown id)

This commit is contained in:
Igor Velho
2026-08-24 14:47:59 +01:00
parent 48ca2fdf43
commit 9ae30bd412
@@ -1,6 +1,6 @@
import { describe, expect, test } from 'bun:test';
import type { Session } from '@opencode-ai/sdk/v2';
import { buildChildrenIndex, formatCost } from './subagentCost';
import { buildChildrenIndex, computeSubtreeCost, formatCost } from './subagentCost';
function makeSession(id: string, cost: number, parentID?: string): Session {
return { id, cost, parentID } as unknown as Session;
@@ -23,3 +23,50 @@ describe('formatCost', () => {
expect(formatCost(2)).toBe('$2');
});
});
describe('computeSubtreeCost', () => {
test('sums a flat root with two direct children', () => {
const root = makeSession('root', 1);
const childA = makeSession('a', 2, 'root');
const childB = makeSession('b', 3, 'root');
const sessions = [root, childA, childB];
const sessionsById = new Map(sessions.map((s) => [s.id, s]));
const childrenByParent = buildChildrenIndex(sessions);
expect(computeSubtreeCost('root', sessionsById, childrenByParent)).toBe(6);
});
test('rolls up cost through nested descendants', () => {
const root = makeSession('root', 1);
const child = makeSession('child', 2, 'root');
const grandchild = makeSession('grandchild', 4, 'child');
const sessions = [root, child, grandchild];
const sessionsById = new Map(sessions.map((s) => [s.id, s]));
const childrenByParent = buildChildrenIndex(sessions);
expect(computeSubtreeCost('root', sessionsById, childrenByParent)).toBe(7);
expect(computeSubtreeCost('child', sessionsById, childrenByParent)).toBe(6);
});
test('does not double-count or infinite-loop on a cycle', () => {
const a = makeSession('a', 1, 'b');
const b = makeSession('b', 2, 'a');
const sessions = [a, b];
const sessionsById = new Map(sessions.map((s) => [s.id, s]));
const childrenByParent = buildChildrenIndex(sessions);
expect(computeSubtreeCost('a', sessionsById, childrenByParent)).toBe(3);
});
test('treats zero and undefined cost as zero, not a break', () => {
const root = makeSession('root', 0);
const child = { id: 'child', parentID: 'root' } as unknown as Session;
const sessions = [root, child];
const sessionsById = new Map(sessions.map((s) => [s.id, s]));
const childrenByParent = buildChildrenIndex(sessions);
expect(computeSubtreeCost('root', sessionsById, childrenByParent)).toBe(0);
});
test('returns 0 for an unknown id', () => {
const sessionsById = new Map<string, Session>();
const childrenByParent = new Map<string, Session[]>();
expect(computeSubtreeCost('missing', sessionsById, childrenByParent)).toBe(0);
});
});