test(ai): expand AI flow and clipboard semantic coverage

- Cover reply-variant decision paths, scene-detector abstention, and
  the merged reply center stance catalog.
- Lock in clipboard semantic analyzer thresholds, complaint-only
  suppression, and existing-skill routing.
- Add durable session, refresh, and managed-gateway reliability tests
  for the Apple account path.
- Verify personal-style prompt derivation, low-confidence ASR
  tendencies, and Polish style learning against real corpus evidence.
- Exercise the assistant keyboard and Polish styles UI flows in
  end-to-end UI tests.
This commit is contained in:
Rocky
2026-08-29 11:51:25 +08:00
parent 3c10d73d7f
commit b275b6b0d9
15 changed files with 1348 additions and 125 deletions
+79
View File
@@ -350,6 +350,85 @@ final class LLMClientTests: XCTestCase {
}
}
func testAppGroupStoreUsesSelectedCredentialChannelForStyleLearning() {
let suiteName = "group.com.osgkeyboard.shared.tests.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suiteName)!
defaults.removePersistentDomain(forName: suiteName)
defer { defaults.removePersistentDomain(forName: suiteName) }
defaults.set(
CredentialSource.managed.rawValue,
forKey: AppGroupConfiguration.Keys.credentialSource
)
let managedStore = AppGroupStore(defaults: defaults)
let managedClient = managedStore.makeClient(taskKind: .customSkill)
XCTAssertEqual(
(managedClient as? ManagedLLMClient)?.capability,
.assistant
)
defaults.set(
CredentialSource.byok.rawValue,
forKey: AppGroupConfiguration.Keys.credentialSource
)
let byokStore = AppGroupStore(defaults: defaults)
XCTAssertFalse(
byokStore.makeClient(taskKind: .customSkill) is ManagedLLMClient
)
}
func testLiveConfigurationStoreSnapshotsAnyConfigurationStore() throws {
let suiteName = "group.com.osgkeyboard.shared.tests.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suiteName)!
defaults.removePersistentDomain(forName: suiteName)
defer { defaults.removePersistentDomain(forName: suiteName) }
let config = ProviderConfig(defaults: defaults)
config.providerId = "openai"
config.baseURL = "https://snapshot.example/v1"
config.apiKey = "snapshot-key"
config.model = "snapshot-model"
config.credentialSource = .managed
config.polishIntensity = .heavy
config.llmThinkingEnabled = true
let source = AppGroupStore(defaults: defaults)
var catalog = PolishStyleCatalog()
let style = PolishStylePack(
id: "user.snapshot-config",
name: "Snapshot",
prompt: "Keep this style fixed."
)
try catalog.upsert(style)
source.setPolishStyleCatalog(catalog)
source.setActivePolishStyleId(style.id)
let captured = LiveConfigurationStore(store: source as any ConfigurationStore)
config.providerId = "deepseek"
config.baseURL = "https://changed.example/v1"
config.apiKey = "changed-key"
config.model = "changed-model"
config.credentialSource = .byok
config.polishIntensity = .light
config.llmThinkingEnabled = false
source.setActivePolishStyleId(PolishStylePackCatalog.defaultID)
XCTAssertEqual(captured.providerId, "openai")
XCTAssertEqual(captured.baseURL, "https://snapshot.example/v1")
XCTAssertEqual(captured.apiKey, "snapshot-key")
XCTAssertEqual(captured.model, "snapshot-model")
XCTAssertEqual(captured.credentialSource, .managed)
XCTAssertEqual(captured.polishIntensity, .heavy)
XCTAssertTrue(captured.llmThinkingEnabled)
XCTAssertEqual(captured.activePolishStyleId, style.id)
let capturedStyle = try XCTUnwrap(
captured.polishStyleCatalog.entries.first(where: { $0.id == style.id })
)
XCTAssertEqual(capturedStyle.name, style.name)
XCTAssertEqual(capturedStyle.prompt, style.prompt)
}
// MARK: - TEST-2: cloud always polishes (legacy modeId ignored)
/// Cloud engine must invoke the LLM even when a legacy `modeId == "off"`