hermes-agent/ui-tui/src/__tests__/virtualHeights.test.ts
brooklyn! 42f9234da3
feat(tui): segment turns with rule above non-first user msgs; trim ticker dead space (#21846)
Multi-turn transcripts ran together visually because every user message
got the same vertical rhythm regardless of position. Adds a short ─── in
the border colour above every user message after the first, so each turn
reads as its own block. Height estimator gains a `withSeparator` flag so
virtual scrolling pre-allocates the extra two rows (rule + top margin)
and avoids a jump on first measurement.

While in the area: the busy-indicator duration was padded with
`padStart(7)`, leaving five visible spaces between `·` and the digits
(`⠋ ·      2s`) — especially loud under the verb-less `unicode` style.
Drop the padding entirely (`⠋ · 2s`); the model label now shifts a few
columns as the duration grows, which is the right trade-off for the
minimal indicator styles. The verb-padding test stays; the
duration-padding test is removed alongside the function it covered.
2026-05-08 05:12:09 -07:00

42 lines
1.8 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 { describe, expect, it } from 'vitest'
import { estimatedMsgHeight, messageHeightKey, wrappedLines } from '../lib/virtualHeights.js'
import type { Msg } from '../types.js'
describe('virtual height estimates', () => {
it('uses stable content keys across resumed message objects', () => {
const msg: Msg = { role: 'assistant', text: 'same text', tools: ['Search Files [long message]'] }
expect(messageHeightKey(msg)).toBe(messageHeightKey({ ...msg }))
})
it('accounts for wrapping and preserved blank-block rhythm', () => {
const msg: Msg = { role: 'assistant', text: `one\n\n${'x'.repeat(90)}` }
expect(wrappedLines(msg.text, 30)).toBe(5)
expect(estimatedMsgHeight(msg, 35, { compact: false, details: false })).toBeGreaterThan(5)
})
it('uses compound user prompt width when estimating user message wrapping', () => {
const msg: Msg = { role: 'user', text: 'x'.repeat(21) }
expect(estimatedMsgHeight(msg, 26, { compact: false, details: false, userPrompt: '' })).toBe(3)
expect(estimatedMsgHeight(msg, 26, { compact: false, details: false, userPrompt: 'Ψ >' })).toBe(4)
})
it('includes detail sections when visible', () => {
const msg: Msg = { role: 'assistant', text: 'ok', thinking: 'line 1\nline 2', tools: ['Tool A', 'Tool B'] }
expect(estimatedMsgHeight(msg, 80, { compact: false, details: true })).toBeGreaterThan(
estimatedMsgHeight(msg, 80, { compact: false, details: false })
)
})
it('reserves two extra rows for the inter-turn separator on non-first user messages', () => {
const msg: Msg = { role: 'user', text: 'follow-up question' }
const base = estimatedMsgHeight(msg, 80, { compact: false, details: false })
const withSep = estimatedMsgHeight(msg, 80, { compact: false, details: false, withSeparator: true })
expect(withSep).toBe(base + 2)
})
})