| |
| |
| |
| |
| import { describe, it, expect } from 'vitest'; |
| import { createStreamingTts, streamTtsInternals } from './streamTts'; |
| const { splitIntoSentences, NullStreamTts } = streamTtsInternals; |
| describe('splitIntoSentences', () => { |
| it('splits on sentence enders followed by whitespace', () => { |
| const { sentences, remainder } = splitIntoSentences('hello there. how are you? fine! and you'); |
| expect(sentences).toEqual([ |
| 'hello there.', |
| 'how are you?', |
| 'fine!', |
| ]); |
| expect(remainder).toBe('and you'); |
| }); |
| it('keeps partial trailing text as remainder', () => { |
| const { sentences, remainder } = splitIntoSentences('partial sentence'); |
| expect(sentences).toEqual([]); |
| expect(remainder).toBe('partial sentence'); |
| }); |
| it('is safe on empty input', () => { |
| const { sentences, remainder } = splitIntoSentences(''); |
| expect(sentences).toEqual([]); |
| expect(remainder).toBe(''); |
| }); |
| it('splits on newlines + semicolons', () => { |
| const { sentences, remainder } = splitIntoSentences('one thing;\n another thing.\n tail'); |
| |
| expect(sentences.length).toBeGreaterThanOrEqual(2); |
| expect(sentences[0]).toContain('one thing'); |
| expect(remainder.trim()).toBe('tail'); |
| }); |
| }); |
| describe('NullStreamTts fallback', () => { |
| it('is safe to call every method; never claims to be speaking', () => { |
| const tts = new NullStreamTts(); |
| expect(tts.isSpeaking).toBe(false); |
| tts.appendDelta('hello'); |
| tts.flush(); |
| tts.stop(); |
| expect(tts.isSpeaking).toBe(false); |
| }); |
| }); |
| describe('createStreamingTts factory', () => { |
| it('returns an object implementing the StreamingTts contract', () => { |
| const tts = createStreamingTts(); |
| expect(typeof tts.appendDelta).toBe('function'); |
| expect(typeof tts.flush).toBe('function'); |
| expect(typeof tts.stop).toBe('function'); |
| expect(typeof tts.isSpeaking).toBe('boolean'); |
| }); |
| }); |
|
|