feat(keyboard): ship AI mode surface with streaming search answers
Add the AI keyboard tab, Agent settings, and user-owned LLM key path for 1.7.0, including streaming answers and web-search transports without the built-in DeepSeek fallback.
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import XCTest
|
||||
@testable import OSGKeyboardShared
|
||||
|
||||
final class AIHistoryAndUsageTests: XCTestCase {
|
||||
@MainActor
|
||||
func testAIHistoryMutationPreservesSource() throws {
|
||||
let defaults = try makeDefaults()
|
||||
let store = SpeechHistoryStore(defaults: defaults)
|
||||
let mutation = HistoryMutation(
|
||||
action: .append,
|
||||
entryID: UUID(),
|
||||
text: "AI 答案",
|
||||
engineMode: "local",
|
||||
source: .ai,
|
||||
usageCategory: .ai
|
||||
)
|
||||
|
||||
let entry = try XCTUnwrap(store.applyHistoryMutation(mutation))
|
||||
|
||||
XCTAssertEqual(entry.text, "AI 答案")
|
||||
XCTAssertEqual(entry.source, .ai)
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func testAICharacterCommitIsIdempotent() throws {
|
||||
let defaults = try makeDefaults()
|
||||
let store = UsageStatisticsStore(defaults: defaults)
|
||||
let commitID = UUID()
|
||||
|
||||
store.recordAIInsertion(text: "四个字符", commitID: commitID)
|
||||
store.recordAIInsertion(text: "四个字符", commitID: commitID)
|
||||
|
||||
XCTAssertEqual(store.aiCharacterCount, 4)
|
||||
XCTAssertEqual(store.totalInputCharacterCount, 4)
|
||||
}
|
||||
|
||||
func testLegacyHistoryEntryDefaultsToDictationSource() throws {
|
||||
let payload: [String: Any] = [
|
||||
"id": UUID().uuidString,
|
||||
"text": "旧记录",
|
||||
"createdAt": Date().timeIntervalSinceReferenceDate,
|
||||
"modifiedAt": Date().timeIntervalSinceReferenceDate,
|
||||
"revision": 0,
|
||||
]
|
||||
let data = try JSONSerialization.data(withJSONObject: payload)
|
||||
let decoder = JSONDecoder()
|
||||
|
||||
let entry = try decoder.decode(SpeechHistoryEntry.self, from: data)
|
||||
|
||||
XCTAssertEqual(entry.source, .dictation)
|
||||
}
|
||||
|
||||
private func makeDefaults() throws -> UserDefaults {
|
||||
let name = "AIHistoryAndUsageTests.\(UUID().uuidString)"
|
||||
let defaults = try XCTUnwrap(UserDefaults(suiteName: name))
|
||||
defaults.removePersistentDomain(forName: name)
|
||||
return defaults
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user