Repository navigation
Expand file tree
/
Copy pathband.test.ts
More file actions
90 lines (81 loc) · 3.32 KB
/
Copy pathband.test.ts
File metadata and controls
90 lines (81 loc) · 3.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import { expect, mock, test } from 'claude-code/testing'
import type { On } from 'claude-code'
const OPTS = { options: { apiKey: 'k-test', mode: 'balanced' } }
const PROPS = {
hasSurvey: false,
isWorking: false,
maxRows: 10,
bodyColumns: 120,
scroll: { offset: 0, bodyRows: 10 },
view: {},
} as any
// Only what a routed turn needs: a Jev answer, the session model and the turn bottom.
function stubs(on: On, failJev = false) {
mock.clock(on)
on('http.fetch', async () => ({
value: failJev ? { headers: {}, ok: false, status: 500, text: 'boom' } : {
headers: {},
ok: true,
status: 200,
text: JSON.stringify({
answers: {
model: { type: 'choice', choice: 'opus', confidence: 0.9 },
effort: { type: 'choice', choice: 'high', confidence: 0.8 },
},
}),
},
}))
on('session.model', async () => ({ value: 'claude-sonnet-5-5' }))
on('session.messages', async () => ({ value: [] }))
on('ui.toast', async () => ({ value: undefined }))
on('command.register', async (_$, e) => ({ value: { command: e.name } }))
on('turn.start', async (_$, e) => ({ turnId: e.turnId }))
}
const mountBand = ($: any, props = PROPS) => $.ui.mount({ plugin: 'jev-router', surface: 'terminal', component: 'AbovePrompt', props })
test('the band waits for the first task before any decision', OPTS, async ($, on) => {
stubs(on)
const ui = await mountBand($)
const band = JSON.stringify(await ui.drawn())
expect(band).toContain('JEV')
expect(band).toContain('waiting for the first task')
await ui.unmount()
})
test('the band shows the model alias after a routed turn', OPTS, async ($, on) => {
stubs(on)
await $.turn.start({ text: 'Design a sharded job queue', turnId: 't1' })
const ui = await mountBand($)
const band = JSON.stringify(await ui.drawn())
expect(band).toContain('opus')
expect(band).not.toContain('waiting for the first task')
await ui.unmount()
})
// A step that reports the model it really ran on, whatever the router asked for.
function stepOn(on: On, model: string) {
on('turn.step', async function* (_$, e) {
return { turnId: e.turnId, index: e.index, answer: '', toolUses: [], stopReason: 'end_turn', usage: { model, input_tokens: 10, output_tokens: 10, cache_read_input_tokens: 0, cache_creation_input_tokens: 0 } }
})
}
const step = ($: any, turnId: string) => $.turn.step({ turnId, index: 0, model: 'claude-sonnet-5-5', effort: 'medium', messageCount: 1 })
test('the band flags a step that ran on another model than the pick', OPTS, async ($, on) => {
stubs(on)
stepOn(on, 'claude-sonnet-5-5') // the router picked opus
await $.turn.start({ text: 'Design a sharded job queue', turnId: 't1' })
for await (const _ of step($, 't1')) {
}
const ui = await mountBand($)
const band = JSON.stringify(await ui.drawn())
expect(band).toContain('picked opus')
await ui.unmount()
})
test('the band shows the session model after a Jev failure instead of waiting', OPTS, async ($, on) => {
stubs(on, true)
stepOn(on, 'claude-sonnet-5-5')
await $.turn.start({ text: 'Design a sharded job queue', turnId: 't1' })
for await (const _ of step($, 't1')) {
}
const ui = await mountBand($)
const band = JSON.stringify(await ui.drawn())
expect(band).toContain('session model')
expect(band).not.toContain('waiting for the first task')
await ui.unmount()
})