Files
OSGKeyboard/OSGKeyboardTests/AIHintPoolTests.swift
T
Rocky 9f308fadd2 feat(keyboard): ship AI hint carousel, home library cards, and clipboard polish
Rotate AI idle suggestions with optional remote packs, move history/dictionary onto self-sizing Home preview cards, harden clipboard capture/prompting, and simplify keyboard chrome by dropping most liquid-glass shadows.
2026-08-13 01:00:51 +08:00

128 lines
4.9 KiB
Swift

// AIHintPoolTests.swift
// OSGKeyboardTests
import XCTest
@testable import OSGKeyboardShared
final class AIHintPoolTests: XCTestCase {
func testLocaleResolverOnlyZhHansUsesChinesePack() {
XCTAssertEqual(AIHintLocaleResolver.packLocale(preferredLanguages: ["zh-Hans"]), "zh")
XCTAssertEqual(AIHintLocaleResolver.packLocale(preferredLanguages: ["zh-Hans-CN"]), "zh")
XCTAssertEqual(AIHintLocaleResolver.packLocale(preferredLanguages: ["zh-Hant"]), "en")
XCTAssertEqual(AIHintLocaleResolver.packLocale(preferredLanguages: ["en-US"]), "en")
}
func testClipboardWindowForcesOnlyClipboardCards() {
let pack = AIHintPack(
locale: "zh",
cards: AIHintLocalCatalog.cards(locale: "zh")
)
let recent = ClipboardHistoryEntry(text: "hello", createdAt: Date())
let cards = AIHintPool.activeCards(
pack: pack,
clipboardHistoryEnabled: true,
newestClipboard: recent
)
XCTAssertFalse(cards.isEmpty)
XCTAssertTrue(cards.allSatisfy(\.requiresClipboard30s))
}
func testClipboardDisabledDropsClipboardCards() {
let pack = AIHintPack(
locale: "zh",
cards: AIHintLocalCatalog.cards(locale: "zh")
)
let cards = AIHintPool.activeCards(
pack: pack,
clipboardHistoryEnabled: false,
newestClipboard: ClipboardHistoryEntry(text: "hello")
)
XCTAssertFalse(cards.isEmpty)
XCTAssertTrue(cards.allSatisfy { !$0.requiresClipboard30s })
}
func testResolvePromptEmbedsClipboardMaterialAsData() throws {
let card = AIHintLocalCatalog.cards(locale: "zh")
.first { $0.id == "local-zh-clipboard-reply" }!
guard case .ready(let prompt) = AIHintPool.resolvePrompt(
for: card,
clipboardText: "你好"
) else {
return XCTFail("expected a ready prompt")
}
XCTAssertTrue(prompt.contains("<clipboard_text>"))
XCTAssertTrue(prompt.contains("你好"))
XCTAssertFalse(prompt.contains(AIClipboardPrompt.materialPlaceholder))
}
func testExpiredReadyPackFallsBackToLocalCatalog() {
let suiteName = "AIHintPoolTests.\(UUID().uuidString)"
let suite = UserDefaults(suiteName: suiteName)!
defer { suite.removePersistentDomain(forName: suiteName) }
let remoteCard = AIHintCard(
id: "remote-hot",
displayText: "聊聊热点",
prompt: "请概括今日热点",
category: "society",
source: "tophub"
)
AIHintStore.saveReadyPack(
AIHintPack(
locale: "zh",
expiresAt: "2026-01-01T00:00:00Z",
cards: [remoteCard]
),
defaults: suite
)
let resolved = AIHintStore.resolvedPack(
locale: "zh",
now: Date(timeIntervalSince1970: 1_800_000_000),
defaults: suite
)
XCTAssertFalse(resolved.cards.contains { $0.id == remoteCard.id })
XCTAssertEqual(resolved.cards, AIHintLocalCatalog.cards(locale: "zh"))
}
func testFreshReadyPackIsServedAndTrackedPerLocale() {
let suiteName = "AIHintPoolTests.\(UUID().uuidString)"
let suite = UserDefaults(suiteName: suiteName)!
defer { suite.removePersistentDomain(forName: suiteName) }
let card = AIHintCard(
id: "remote-fresh",
displayText: "看今日早报",
prompt: "请概括今日要点",
category: "daily"
)
AIHintStore.saveReadyPack(
AIHintPack(locale: "zh", cards: [card]),
defaults: suite
)
XCTAssertEqual(
AIHintStore.resolvedPack(locale: "zh", defaults: suite).cards,
[card]
)
XCTAssertFalse(AIHintStore.shouldRefresh(locale: "zh", defaults: suite))
// en never succeeded, so the pass must still run.
XCTAssertTrue(AIHintStore.shouldRefresh(locale: "en", defaults: suite))
XCTAssertTrue(AIHintStore.shouldRefresh(defaults: suite))
}
func testKeywordCompressorParseDisplayMap() {
let raw = #"[{"id":"a","displayText":"聊聊热点"},{"id":"b","displayText":"上海天气怎么样"}]"#
let map = AIHintKeywordCompressor.parseDisplayMap(from: raw)
XCTAssertEqual(map["a"], "聊聊热点")
XCTAssertEqual(map["b"], "上海天气怎么样")
}
func testRemotePackDecodesTextAsDisplayText() throws {
let json = """
{"locale":"zh","generatedAt":"2026-01-01T00:00:00Z","expiresAt":"2026-01-01T12:00:00Z","version":1,"cards":[{"id":"x","text":"全网热点:很长","prompt":"请概括","category":"society","priority":70,"source":"tophub","locale":"zh","conditions":[]}]}
"""
let pack = try JSONDecoder().decode(AIHintPack.self, from: Data(json.utf8))
XCTAssertEqual(pack.cards.first?.displayText, "全网热点:很长")
}
}