hermes-agent/apps/desktop/src/lib/speech-text.test.ts
hermes-seaeye[bot] 66e20786d0
fmt(js): npm run fix on merge (#73666)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-28 21:55:38 +00:00

152 lines
4.2 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { sanitizeTextForSpeech } from './speech-text'
describe('sanitizeTextForSpeech', () => {
it('summarizes fenced code blocks instead of reading them literally', () => {
expect(sanitizeTextForSpeech('Here is code:\n```ts\nconst x = 1\n```\nDone.')).toBe(
'Here is code: code block omitted Done.'
)
})
it('still keeps normal prose and inline code readable', () => {
expect(sanitizeTextForSpeech('Use `git status` after the change.')).toBe('Use git status after the change.')
})
it('skips markdown table data while preserving surrounding human text', () => {
const text = `Here is the quick takeaway: the totals remain unchanged.
| Item | Value | Notes |
| --- | ---: | --- |
| Example A | 10 | first row |
| Example B | 20 | second row |
Full detail stays visible on screen.`
expect(sanitizeTextForSpeech(text)).toBe(
'Here is the quick takeaway: the totals remain unchanged. Full detail stays visible on screen.'
)
})
it('does not strip prose that merely contains a pipe character', () => {
const text = 'Use the summary first | keep the table on screen when it matters.'
expect(sanitizeTextForSpeech(text)).toBe('Use the summary first | keep the table on screen when it matters.')
})
it('does not duplicate punctuation across paragraph breaks', () => {
const text = `First sentence.
Second sentence.`
expect(sanitizeTextForSpeech(text)).toBe('First sentence. Second sentence.')
})
it.each([
['markdown emphasis', '**First sentence.**\n\nSecond sentence.', 'First sentence. Second sentence.'],
['a closing quote', '“First sentence.”\n\nSecond sentence.', '“First sentence.” Second sentence.'],
['a closing parenthesis', '(First sentence.)\n\nSecond sentence.', '(First sentence.) Second sentence.']
])('does not duplicate punctuation after %s', (_label, text, expected) => {
expect(sanitizeTextForSpeech(text)).toBe(expected)
})
it('skips markdown tables without leading and trailing pipes', () => {
const text = `Main takeaway: total is unchanged.
Item | Value
--- | ---:
Example A | 10
Example B | 20
Done.`
expect(sanitizeTextForSpeech(text)).toBe('Main takeaway: total is unchanged. Done.')
})
it('skips markdown tables nested inside blockquotes', () => {
const text = `Before the table.
> | Item | Value |
> | --- | ---: |
> | Example A | 10 |
> | Example B | 20 |
After the table.`
expect(sanitizeTextForSpeech(text)).toBe('Before the table. After the table.')
})
it('allows marker padding plus three spaces in blockquoted tables', () => {
const text = `Before the table.
> | Item | Value |
> | --- | ---: |
> | Example A | 10 |
After the table.`
expect(sanitizeTextForSpeech(text)).toBe('Before the table. After the table.')
})
it('skips explicit single-column markdown tables', () => {
const text = `Before the table.
| Item |
| --- |
| Example A |
After the table.`
expect(sanitizeTextForSpeech(text)).toBe('Before the table. After the table.')
})
it('preserves rows outside a table blockquote', () => {
const text = `> | Item | Value |
> | --- | ---: |
> | Example A | 10 |
Outside | prose`
expect(sanitizeTextForSpeech(text)).toBe('Outside | prose')
})
it('preserves malformed tables with mismatched column counts', () => {
const text = `Heading | Detail
--- | --- | ---
Keep this prose.`
expect(sanitizeTextForSpeech(text)).toContain('Heading | Detail')
})
it('skips GFM body rows whose cell counts differ from the header', () => {
const text = `Before the table.
| Item | Value |
| --- | ---: |
| Example A |
| Example B | 20 | ignored |
After the table.`
expect(sanitizeTextForSpeech(text)).toBe('Before the table. After the table.')
})
it('skips tables containing escaped pipe characters', () => {
const text = `Before the table.
| Item \\| detail | Value |
| --- | ---: |
| Example A | 10 |
After the table.`
expect(sanitizeTextForSpeech(text)).toBe('Before the table. After the table.')
})
it('preserves indented code that resembles a table', () => {
const text = ` Item | Value
--- | ---
Example A | 10`
expect(sanitizeTextForSpeech(text)).toContain('Item | Value')
})
})