mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
test: decouple ios talk parsing coverage
This commit is contained in:
76
apps/ios/Tests/Logic/TalkConfigParsingTests.swift
Normal file
76
apps/ios/Tests/Logic/TalkConfigParsingTests.swift
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import Foundation
|
||||||
|
import OpenClawKit
|
||||||
|
import Testing
|
||||||
|
|
||||||
|
private let iOSSilenceTimeoutMs = 900
|
||||||
|
|
||||||
|
@Suite struct TalkConfigParsingTests {
|
||||||
|
@Test func prefersNormalizedTalkProviderPayload() {
|
||||||
|
let talk: [String: Any] = [
|
||||||
|
"provider": "elevenlabs",
|
||||||
|
"providers": [
|
||||||
|
"elevenlabs": [
|
||||||
|
"voiceId": "voice-normalized",
|
||||||
|
],
|
||||||
|
],
|
||||||
|
"voiceId": "voice-legacy",
|
||||||
|
]
|
||||||
|
|
||||||
|
let selection = TalkConfigParsing.selectProviderConfig(
|
||||||
|
TalkConfigParsing.bridgeFoundationDictionary(talk),
|
||||||
|
defaultProvider: "elevenlabs",
|
||||||
|
allowLegacyFallback: false)
|
||||||
|
#expect(selection?.provider == "elevenlabs")
|
||||||
|
#expect(selection?.config["voiceId"]?.stringValue == "voice-normalized")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test func ignoresLegacyTalkFieldsWhenNormalizedPayloadMissing() {
|
||||||
|
let talk: [String: Any] = [
|
||||||
|
"voiceId": "voice-legacy",
|
||||||
|
"apiKey": "legacy-key", // pragma: allowlist secret
|
||||||
|
]
|
||||||
|
|
||||||
|
let selection = TalkConfigParsing.selectProviderConfig(
|
||||||
|
TalkConfigParsing.bridgeFoundationDictionary(talk),
|
||||||
|
defaultProvider: "elevenlabs",
|
||||||
|
allowLegacyFallback: false)
|
||||||
|
#expect(selection == nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test func readsConfiguredSilenceTimeoutMs() {
|
||||||
|
let talk: [String: Any] = [
|
||||||
|
"silenceTimeoutMs": 1500,
|
||||||
|
]
|
||||||
|
|
||||||
|
#expect(
|
||||||
|
TalkConfigParsing.resolvedSilenceTimeoutMs(
|
||||||
|
TalkConfigParsing.bridgeFoundationDictionary(talk),
|
||||||
|
fallback: iOSSilenceTimeoutMs) == 1500)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test func defaultsSilenceTimeoutMsWhenMissing() {
|
||||||
|
#expect(TalkConfigParsing.resolvedSilenceTimeoutMs(nil, fallback: iOSSilenceTimeoutMs) == iOSSilenceTimeoutMs)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test func defaultsSilenceTimeoutMsWhenInvalid() {
|
||||||
|
let talk: [String: Any] = [
|
||||||
|
"silenceTimeoutMs": 0,
|
||||||
|
]
|
||||||
|
|
||||||
|
#expect(
|
||||||
|
TalkConfigParsing.resolvedSilenceTimeoutMs(
|
||||||
|
TalkConfigParsing.bridgeFoundationDictionary(talk),
|
||||||
|
fallback: iOSSilenceTimeoutMs) == iOSSilenceTimeoutMs)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test func defaultsSilenceTimeoutMsWhenBool() {
|
||||||
|
let talk: [String: Any] = [
|
||||||
|
"silenceTimeoutMs": true,
|
||||||
|
]
|
||||||
|
|
||||||
|
#expect(
|
||||||
|
TalkConfigParsing.resolvedSilenceTimeoutMs(
|
||||||
|
TalkConfigParsing.bridgeFoundationDictionary(talk),
|
||||||
|
fallback: iOSSilenceTimeoutMs) == iOSSilenceTimeoutMs)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,38 +1,9 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import OpenClawKit
|
|
||||||
import Testing
|
import Testing
|
||||||
@testable import OpenClaw
|
@testable import OpenClaw
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
@Suite struct TalkModeConfigParsingTests {
|
@Suite struct TalkModeManagerTests {
|
||||||
@Test func prefersNormalizedTalkProviderPayload() {
|
|
||||||
let talk: [String: Any] = [
|
|
||||||
"provider": "elevenlabs",
|
|
||||||
"providers": [
|
|
||||||
"elevenlabs": [
|
|
||||||
"voiceId": "voice-normalized",
|
|
||||||
],
|
|
||||||
],
|
|
||||||
"voiceId": "voice-legacy",
|
|
||||||
]
|
|
||||||
|
|
||||||
let selection = TalkModeManager.selectTalkProviderConfig(
|
|
||||||
TalkConfigParsing.bridgeFoundationDictionary(talk))
|
|
||||||
#expect(selection?.provider == "elevenlabs")
|
|
||||||
#expect(selection?.config["voiceId"]?.stringValue == "voice-normalized")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func ignoresLegacyTalkFieldsWhenNormalizedPayloadMissing() {
|
|
||||||
let talk: [String: Any] = [
|
|
||||||
"voiceId": "voice-legacy",
|
|
||||||
"apiKey": "legacy-key", // pragma: allowlist secret
|
|
||||||
]
|
|
||||||
|
|
||||||
let selection = TalkModeManager.selectTalkProviderConfig(
|
|
||||||
TalkConfigParsing.bridgeFoundationDictionary(talk))
|
|
||||||
#expect(selection == nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func detectsPCMFormatRejectionFromElevenLabsError() {
|
@Test func detectsPCMFormatRejectionFromElevenLabsError() {
|
||||||
let error = NSError(
|
let error = NSError(
|
||||||
domain: "ElevenLabsTTS",
|
domain: "ElevenLabsTTS",
|
||||||
@@ -50,32 +21,4 @@ import Testing
|
|||||||
userInfo: [NSLocalizedDescriptionKey: "queue enqueue failed"])
|
userInfo: [NSLocalizedDescriptionKey: "queue enqueue failed"])
|
||||||
#expect(TalkModeManager._test_isPCMFormatRejectedByAPI(error) == false)
|
#expect(TalkModeManager._test_isPCMFormatRejectedByAPI(error) == false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test func readsConfiguredSilenceTimeoutMs() {
|
|
||||||
let talk: [String: Any] = [
|
|
||||||
"silenceTimeoutMs": 1500,
|
|
||||||
]
|
|
||||||
|
|
||||||
#expect(TalkModeManager.resolvedSilenceTimeoutMs(TalkConfigParsing.bridgeFoundationDictionary(talk)) == 1500)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func defaultsSilenceTimeoutMsWhenMissing() {
|
|
||||||
#expect(TalkModeManager.resolvedSilenceTimeoutMs(nil) == TalkDefaults.silenceTimeoutMs)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func defaultsSilenceTimeoutMsWhenInvalid() {
|
|
||||||
let talk: [String: Any] = [
|
|
||||||
"silenceTimeoutMs": 0,
|
|
||||||
]
|
|
||||||
|
|
||||||
#expect(TalkModeManager.resolvedSilenceTimeoutMs(TalkConfigParsing.bridgeFoundationDictionary(talk)) == TalkDefaults.silenceTimeoutMs)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test func defaultsSilenceTimeoutMsWhenBool() {
|
|
||||||
let talk: [String: Any] = [
|
|
||||||
"silenceTimeoutMs": true,
|
|
||||||
]
|
|
||||||
|
|
||||||
#expect(TalkModeManager.resolvedSilenceTimeoutMs(TalkConfigParsing.bridgeFoundationDictionary(talk)) == TalkDefaults.silenceTimeoutMs)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,15 @@ schemes:
|
|||||||
test:
|
test:
|
||||||
targets:
|
targets:
|
||||||
- OpenClawTests
|
- OpenClawTests
|
||||||
|
- OpenClawLogicTests
|
||||||
|
OpenClawLogicTests:
|
||||||
|
shared: true
|
||||||
|
build:
|
||||||
|
targets:
|
||||||
|
OpenClawLogicTests: all
|
||||||
|
test:
|
||||||
|
targets:
|
||||||
|
- OpenClawLogicTests
|
||||||
|
|
||||||
targets:
|
targets:
|
||||||
OpenClaw:
|
OpenClaw:
|
||||||
@@ -117,8 +126,11 @@ targets:
|
|||||||
NSLocationWhenInUseUsageDescription: OpenClaw uses your location when you allow location sharing.
|
NSLocationWhenInUseUsageDescription: OpenClaw uses your location when you allow location sharing.
|
||||||
NSLocationAlwaysAndWhenInUseUsageDescription: OpenClaw can share your location in the background when you enable Always.
|
NSLocationAlwaysAndWhenInUseUsageDescription: OpenClaw can share your location in the background when you enable Always.
|
||||||
NSMicrophoneUsageDescription: OpenClaw needs microphone access for voice wake.
|
NSMicrophoneUsageDescription: OpenClaw needs microphone access for voice wake.
|
||||||
|
NSMotionUsageDescription: OpenClaw may use motion data to support device-aware interactions and automations.
|
||||||
|
NSPhotoLibraryUsageDescription: OpenClaw needs photo library access when you choose existing photos to share with your assistant.
|
||||||
NSSpeechRecognitionUsageDescription: OpenClaw uses on-device speech recognition for voice wake.
|
NSSpeechRecognitionUsageDescription: OpenClaw uses on-device speech recognition for voice wake.
|
||||||
NSSupportsLiveActivities: true
|
NSSupportsLiveActivities: true
|
||||||
|
ITSAppUsesNonExemptEncryption: false
|
||||||
UISupportedInterfaceOrientations:
|
UISupportedInterfaceOrientations:
|
||||||
- UIInterfaceOrientationPortrait
|
- UIInterfaceOrientationPortrait
|
||||||
- UIInterfaceOrientationPortraitUpsideDown
|
- UIInterfaceOrientationPortraitUpsideDown
|
||||||
@@ -259,6 +271,8 @@ targets:
|
|||||||
Release: Signing.xcconfig
|
Release: Signing.xcconfig
|
||||||
sources:
|
sources:
|
||||||
- path: Tests
|
- path: Tests
|
||||||
|
excludes:
|
||||||
|
- Logic
|
||||||
dependencies:
|
dependencies:
|
||||||
- target: OpenClaw
|
- target: OpenClaw
|
||||||
- package: Swabble
|
- package: Swabble
|
||||||
@@ -281,3 +295,29 @@ targets:
|
|||||||
CFBundleDisplayName: OpenClawTests
|
CFBundleDisplayName: OpenClawTests
|
||||||
CFBundleShortVersionString: "2026.3.8"
|
CFBundleShortVersionString: "2026.3.8"
|
||||||
CFBundleVersion: "20260308"
|
CFBundleVersion: "20260308"
|
||||||
|
|
||||||
|
OpenClawLogicTests:
|
||||||
|
type: bundle.unit-test
|
||||||
|
platform: iOS
|
||||||
|
configFiles:
|
||||||
|
Debug: Signing.xcconfig
|
||||||
|
Release: Signing.xcconfig
|
||||||
|
sources:
|
||||||
|
- path: Tests/Logic
|
||||||
|
dependencies:
|
||||||
|
- package: OpenClawKit
|
||||||
|
settings:
|
||||||
|
base:
|
||||||
|
CODE_SIGN_IDENTITY: "Apple Development"
|
||||||
|
CODE_SIGN_STYLE: "$(OPENCLAW_CODE_SIGN_STYLE)"
|
||||||
|
DEVELOPMENT_TEAM: "$(OPENCLAW_DEVELOPMENT_TEAM)"
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER: ai.openclaw.ios.logic-tests
|
||||||
|
ENABLE_APP_INTENTS_METADATA_GENERATION: NO
|
||||||
|
SWIFT_VERSION: "6.0"
|
||||||
|
SWIFT_STRICT_CONCURRENCY: complete
|
||||||
|
info:
|
||||||
|
path: Tests/Info.plist
|
||||||
|
properties:
|
||||||
|
CFBundleDisplayName: OpenClawLogicTests
|
||||||
|
CFBundleShortVersionString: "2026.3.8"
|
||||||
|
CFBundleVersion: "20260308"
|
||||||
|
|||||||
Reference in New Issue
Block a user