2026-04-08 19:31:25 -05:00
|
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
|
|
2026-04-11 17:15:36 -05:00
|
|
|
import { estimateRows, fmtK, isToolTrailResultLine, lastCotTrailIndex, sameToolTrailGroup } from '../lib/text.js'
|
2026-04-09 18:33:25 -05:00
|
|
|
|
|
|
|
|
describe('isToolTrailResultLine', () => {
|
|
|
|
|
it('detects completion markers', () => {
|
|
|
|
|
expect(isToolTrailResultLine('foo ✓')).toBe(true)
|
|
|
|
|
expect(isToolTrailResultLine('foo ✗')).toBe(true)
|
|
|
|
|
expect(isToolTrailResultLine('drafting x…')).toBe(false)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('lastCotTrailIndex', () => {
|
|
|
|
|
it('finds last non-result line', () => {
|
|
|
|
|
expect(lastCotTrailIndex(['a ✓', 'thinking…'])).toBe(1)
|
|
|
|
|
expect(lastCotTrailIndex(['only result ✓'])).toBe(-1)
|
|
|
|
|
})
|
|
|
|
|
})
|
2026-04-08 19:31:25 -05:00
|
|
|
|
2026-04-09 00:36:53 -05:00
|
|
|
describe('sameToolTrailGroup', () => {
|
|
|
|
|
it('matches bare check lines', () => {
|
2026-04-09 18:33:25 -05:00
|
|
|
expect(sameToolTrailGroup('searching', 'searching ✓')).toBe(true)
|
|
|
|
|
expect(sameToolTrailGroup('searching', 'searching ✗')).toBe(true)
|
2026-04-08 19:31:25 -05:00
|
|
|
})
|
|
|
|
|
|
2026-04-09 00:36:53 -05:00
|
|
|
it('matches contextual lines', () => {
|
2026-04-09 18:33:25 -05:00
|
|
|
expect(sameToolTrailGroup('searching', 'searching: * ✓')).toBe(true)
|
|
|
|
|
expect(sameToolTrailGroup('searching', 'searching: foo ✓')).toBe(true)
|
2026-04-08 19:31:25 -05:00
|
|
|
})
|
|
|
|
|
|
2026-04-09 00:36:53 -05:00
|
|
|
it('rejects other tools', () => {
|
2026-04-09 18:33:25 -05:00
|
|
|
expect(sameToolTrailGroup('searching', 'reading ✓')).toBe(false)
|
|
|
|
|
expect(sameToolTrailGroup('searching', 'searching extra ✓')).toBe(false)
|
2026-04-08 19:31:25 -05:00
|
|
|
})
|
|
|
|
|
})
|
2026-04-09 00:46:35 -05:00
|
|
|
|
|
|
|
|
describe('fmtK', () => {
|
|
|
|
|
it('keeps small numbers plain', () => {
|
|
|
|
|
expect(fmtK(999)).toBe('999')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('formats thousands as K', () => {
|
|
|
|
|
expect(fmtK(1000)).toBe('1K')
|
|
|
|
|
expect(fmtK(1500)).toBe('1.5K')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('formats millions and billions', () => {
|
|
|
|
|
expect(fmtK(1_000_000)).toBe('1M')
|
|
|
|
|
expect(fmtK(1_000_000_000)).toBe('1B')
|
|
|
|
|
})
|
|
|
|
|
})
|
2026-04-11 17:15:36 -05:00
|
|
|
|
|
|
|
|
describe('estimateRows', () => {
|
|
|
|
|
it('handles tilde code fences', () => {
|
|
|
|
|
const md = ['~~~markdown', '# heading', '~~~'].join('\n')
|
|
|
|
|
|
|
|
|
|
expect(estimateRows(md, 40)).toBeGreaterThanOrEqual(2)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('handles checklist bullets as list rows', () => {
|
|
|
|
|
const md = ['- [x] done', '- [ ] todo'].join('\n')
|
|
|
|
|
|
|
|
|
|
expect(estimateRows(md, 40)).toBe(2)
|
|
|
|
|
})
|
|
|
|
|
})
|