import { describe, expect, it } from 'vitest' import { cleanTtsText, clampTtsText } from '../../packages/server/src/services/hermes/tts-providers/text' describe('tts provider text helpers', () => { it('removes thinking blocks, code blocks, html, and collapses spaces', () => { expect(cleanTtsText('secretHello `code` world\n```ts\nx()\n```')).toBe('Hello world') }) it('preserves comparison expressions', () => { expect(cleanTtsText('2 < 3 and 5 > 4')).toBe('2 < 3 and 5 > 4') }) it('replaces self-closing html tags with spacing', () => { expect(cleanTtsText('Hello
world')).toBe('Hello world') }) it('removes tags with quoted attributes containing angle brackets', () => { expect(cleanTtsText('Hello a > b world')).toBe('Hello world') }) it('removes html comments', () => { expect(cleanTtsText('Hello world')).toBe('Hello world') }) it('removes html declarations', () => { expect(cleanTtsText('Hello world')).toBe('Hello world') }) it('removes custom self-closing tags', () => { expect(cleanTtsText('A B')).toBe('A B') }) it('removes think blocks', () => { expect(cleanTtsText('Hello secret world')).toBe('Hello world') }) it('keeps words separated when think blocks are adjacent to text', () => { expect(cleanTtsText('Hellosecretworld')).toBe('Hello world') }) it('keeps words separated when fenced code blocks are adjacent to text', () => { expect(cleanTtsText('Hello```ts\nx()\n```world')).toBe('Hello world') }) it('keeps words separated when inline code is adjacent to text', () => { expect(cleanTtsText('foo`code`bar')).toBe('foo bar') }) it('removes unclosed fenced code blocks', () => { expect(cleanTtsText('Hello ```ts\nconst x = 1')).toBe('Hello') }) it('removes markdown fenced code blocks while keeping surrounding prose', () => { expect(cleanTtsText('先说明\n```ts\nconst value = 1\n```\n再继续')).toBe('先说明 再继续') }) it('keeps markdown table text for TTS', () => { expect(cleanTtsText('结果如下:\n| 名称 | 值 |\n| --- | --- |\n| foo | 1 |\n| bar | 2 |\n请确认。')).toBe('结果如下: | 名称 | 值 | | --- | --- | | foo | 1 | | bar | 2 | 请确认。') }) it('removes emoji and decorative symbols before sending text to TTS', () => { expect(cleanTtsText('你好 😊🚀,开始 #1️⃣ -> ✅ done ★')).toBe('你好 ,开始 # -> done') }) it('keeps normal speech punctuation and comparison expressions', () => { expect(cleanTtsText('价格是 $12.5,2 < 3;A+B= C。')).toBe('价格是 $12.5,2 < 3;A+B= C。') }) it('removes zero-width joiner emoji sequences', () => { expect(cleanTtsText('开发者 👨‍💻 正在处理')).toBe('开发者 正在处理') }) it('returns an empty string for empty input', () => { expect(cleanTtsText('')).toBe('') }) it('truncates long text with ellipsis', () => { expect(clampTtsText('abcdef', 5)).toBe('ab...') }) it('returns only an ellipsis when max chars is 3', () => { expect(clampTtsText('abcdef', 3)).toBe('...') }) })