fix(talk): harden TTS + add system fallback
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
import XCTest
|
||||
@testable import ClawdisKit
|
||||
|
||||
final class ElevenLabsTTSValidationTests: XCTestCase {
|
||||
func testValidatedOutputFormatAllowsOnlyMp3Presets() {
|
||||
XCTAssertEqual(ElevenLabsTTSClient.validatedOutputFormat("mp3_44100_128"), "mp3_44100_128")
|
||||
XCTAssertNil(ElevenLabsTTSClient.validatedOutputFormat("pcm_16000"))
|
||||
}
|
||||
|
||||
func testValidatedLanguageAcceptsTwoLetterCodes() {
|
||||
XCTAssertEqual(ElevenLabsTTSClient.validatedLanguage("EN"), "en")
|
||||
XCTAssertNil(ElevenLabsTTSClient.validatedLanguage("eng"))
|
||||
}
|
||||
|
||||
func testValidatedNormalizeAcceptsKnownValues() {
|
||||
XCTAssertEqual(ElevenLabsTTSClient.validatedNormalize("AUTO"), "auto")
|
||||
XCTAssertNil(ElevenLabsTTSClient.validatedNormalize("maybe"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,18 @@ final class TalkDirectiveTests: XCTestCase {
|
||||
XCTAssertEqual(result.stripped, "Hello.")
|
||||
}
|
||||
|
||||
func testSkipsLeadingEmptyLinesWhenParsingDirective() {
|
||||
let text = """
|
||||
|
||||
|
||||
{"voice":"abc123"}
|
||||
Hello there.
|
||||
"""
|
||||
let result = TalkDirectiveParser.parse(text)
|
||||
XCTAssertEqual(result.directive?.voiceId, "abc123")
|
||||
XCTAssertEqual(result.stripped, "Hello there.")
|
||||
}
|
||||
|
||||
func testTracksUnknownKeys() {
|
||||
let text = """
|
||||
{"voice":"abc","mystery":"value","extra":1}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import XCTest
|
||||
@testable import ClawdisKit
|
||||
|
||||
final class TalkHistoryTimestampTests: XCTestCase {
|
||||
func testSecondsTimestampsAreAcceptedWithSmallTolerance() {
|
||||
XCTAssertTrue(TalkHistoryTimestamp.isAfter(999.6, sinceSeconds: 1000))
|
||||
XCTAssertFalse(TalkHistoryTimestamp.isAfter(999.4, sinceSeconds: 1000))
|
||||
}
|
||||
|
||||
func testMillisecondsTimestampsAreAcceptedWithSmallTolerance() {
|
||||
let sinceSeconds = 1_700_000_000.0
|
||||
let sinceMs = sinceSeconds * 1000
|
||||
XCTAssertTrue(TalkHistoryTimestamp.isAfter(sinceMs - 500, sinceSeconds: sinceSeconds))
|
||||
XCTAssertFalse(TalkHistoryTimestamp.isAfter(sinceMs - 501, sinceSeconds: sinceSeconds))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import XCTest
|
||||
@testable import ClawdisKit
|
||||
|
||||
final class TalkPromptBuilderTests: XCTestCase {
|
||||
func testBuildIncludesTranscript() {
|
||||
let prompt = TalkPromptBuilder.build(transcript: "Hello", interruptedAtSeconds: nil)
|
||||
XCTAssertTrue(prompt.contains("Talk Mode active."))
|
||||
XCTAssertTrue(prompt.hasSuffix("\n\nHello"))
|
||||
}
|
||||
|
||||
func testBuildIncludesInterruptionLineWhenProvided() {
|
||||
let prompt = TalkPromptBuilder.build(transcript: "Hi", interruptedAtSeconds: 1.234)
|
||||
XCTAssertTrue(prompt.contains("Assistant speech interrupted at 1.2s."))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import XCTest
|
||||
@testable import ClawdisKit
|
||||
|
||||
final class TalkTTSValidationTests: XCTestCase {
|
||||
func testResolveSpeedUsesRateWPMWhenProvided() {
|
||||
let resolved = TalkTTSValidation.resolveSpeed(speed: nil, rateWPM: 175)
|
||||
XCTAssertNotNil(resolved)
|
||||
XCTAssertEqual(resolved ?? 0, 1.0, accuracy: 0.0001)
|
||||
XCTAssertNil(TalkTTSValidation.resolveSpeed(speed: nil, rateWPM: 400))
|
||||
}
|
||||
|
||||
func testValidatedUnitBounds() {
|
||||
XCTAssertEqual(TalkTTSValidation.validatedUnit(0), 0)
|
||||
XCTAssertEqual(TalkTTSValidation.validatedUnit(1), 1)
|
||||
XCTAssertNil(TalkTTSValidation.validatedUnit(-0.01))
|
||||
XCTAssertNil(TalkTTSValidation.validatedUnit(1.01))
|
||||
}
|
||||
|
||||
func testValidatedSeedBounds() {
|
||||
XCTAssertEqual(TalkTTSValidation.validatedSeed(0), 0)
|
||||
XCTAssertEqual(TalkTTSValidation.validatedSeed(1234), 1234)
|
||||
XCTAssertNil(TalkTTSValidation.validatedSeed(-1))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user