test(mac): cover voice wake helpers

main
Peter Steinberger 2025-12-07 17:56:40 +01:00
parent df9f72134b
commit f3ebb2e9ce
5 changed files with 66 additions and 19 deletions

View File

@ -0,0 +1,22 @@
import Foundation
func sanitizeVoiceWakeTriggers(_ words: [String]) -> [String] {
let cleaned = words
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
.filter { !$0.isEmpty }
return cleaned.isEmpty ? defaultVoiceWakeTriggers : cleaned
}
func normalizeLocaleIdentifier(_ raw: String) -> String {
var trimmed = raw
if let at = trimmed.firstIndex(of: "@") {
trimmed = String(trimmed[..<at])
}
if let u = trimmed.range(of: "-u-") {
trimmed = String(trimmed[..<u.lowerBound])
}
if let t = trimmed.range(of: "-t-") {
trimmed = String(trimmed[..<t.lowerBound])
}
return trimmed
}

View File

@ -209,10 +209,7 @@ struct VoiceWakeSettings: View {
} }
private func sanitizedTriggers() -> [String] { private func sanitizedTriggers() -> [String] {
let cleaned = self.state.swabbleTriggerWords sanitizeVoiceWakeTriggers(self.state.swabbleTriggerWords)
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
.filter { !$0.isEmpty }
return cleaned.isEmpty ? defaultVoiceWakeTriggers : cleaned
} }
private var micPicker: some View { private var micPicker: some View {
@ -343,7 +340,7 @@ struct VoiceWakeSettings: View {
} }
private func friendlyName(for locale: Locale) -> String { private func friendlyName(for locale: Locale) -> String {
let cleanedID = self.normalizedLocaleIdentifier(locale.identifier) let cleanedID = normalizeLocaleIdentifier(locale.identifier)
let cleanLocale = Locale(identifier: cleanedID) let cleanLocale = Locale(identifier: cleanedID)
if let langCode = cleanLocale.language.languageCode?.identifier, if let langCode = cleanLocale.language.languageCode?.identifier,
@ -361,20 +358,6 @@ struct VoiceWakeSettings: View {
return cleanLocale.localizedString(forIdentifier: cleanedID) ?? cleanedID return cleanLocale.localizedString(forIdentifier: cleanedID) ?? cleanedID
} }
private func normalizedLocaleIdentifier(_ raw: String) -> String {
var trimmed = raw
if let at = trimmed.firstIndex(of: "@") {
trimmed = String(trimmed[..<at])
}
if let u = trimmed.range(of: "-u-") {
trimmed = String(trimmed[..<u.lowerBound])
}
if let t = trimmed.range(of: "-t-") {
trimmed = String(trimmed[..<t.lowerBound])
}
return trimmed
}
private var levelMeter: some View { private var levelMeter: some View {
VStack(alignment: .leading, spacing: 6) { VStack(alignment: .leading, spacing: 6) {
HStack(alignment: .center, spacing: 10) { HStack(alignment: .center, spacing: 10) {

View File

@ -190,6 +190,10 @@ final class VoiceWakeTester {
return triggers.contains { lowered.contains($0.lowercased()) } return triggers.contains { lowered.contains($0.lowercased()) }
} }
static func _testMatches(text: String, triggers: [String]) -> Bool {
self.matches(text: text, triggers: triggers)
}
private nonisolated static func ensurePermissions() async throws -> Bool { private nonisolated static func ensurePermissions() async throws -> Bool {
let speechStatus = SFSpeechRecognizer.authorizationStatus() let speechStatus = SFSpeechRecognizer.authorizationStatus()
if speechStatus == .notDetermined { if speechStatus == .notDetermined {

View File

@ -0,0 +1,23 @@
import Testing
@testable import Clawdis
struct VoiceWakeHelpersTests {
@Test func sanitizeTriggersTrimsAndDropsEmpty() {
let cleaned = sanitizeVoiceWakeTriggers([" hi ", " ", "\n", "there"])
#expect(cleaned == ["hi", "there"])
}
@Test func sanitizeTriggersFallsBackToDefaults() {
let cleaned = sanitizeVoiceWakeTriggers([" ", ""])
#expect(cleaned == defaultVoiceWakeTriggers)
}
@Test func normalizeLocaleStripsCollation() {
#expect(normalizeLocaleIdentifier("en_US@collation=phonebook") == "en_US")
}
@Test func normalizeLocaleStripsUnicodeExtensions() {
#expect(normalizeLocaleIdentifier("de-DE-u-co-phonebk") == "de-DE")
#expect(normalizeLocaleIdentifier("ja-JP-t-ja") == "ja-JP")
}
}

View File

@ -0,0 +1,15 @@
import Testing
@testable import Clawdis
struct VoiceWakeTesterTests {
@Test func matchesIsCaseInsensitiveAndSubstring() {
let triggers = ["Claude", "wake word"]
#expect(VoiceWakeTester._testMatches(text: "hey claude are you there", triggers: triggers))
#expect(VoiceWakeTester._testMatches(text: "this has wake word inside", triggers: triggers))
}
@Test func matchesReturnsFalseWhenNoTrigger() {
let triggers = ["claude"]
#expect(!VoiceWakeTester._testMatches(text: "random text", triggers: triggers))
}
}