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
+76 -2
View File
@@ -116,11 +116,11 @@ final class AIReplyVariantTests: XCTestCase {
func testReplyKindOwnsLocalPresentationMetadata() {
XCTAssertEqual(
AIReplyVariant.Kind.allCases.map(\.systemImage),
AIReplyVariantSet.generic.kinds.map(\.systemImage),
["bubble.left.fill", "briefcase.fill", "theatermasks.fill"]
)
XCTAssertEqual(
AIReplyVariant.Kind.allCases.map(\.titleKey),
AIReplyVariantSet.generic.kinds.map(\.titleKey),
[
"keyboard.ai.replyVariant.ordinary",
"keyboard.ai.replyVariant.formal",
@@ -129,6 +129,80 @@ final class AIReplyVariantTests: XCTestCase {
)
}
func testInvitationParserRequiresExactSceneRoles() throws {
let valid = """
{"variants":[
{"kind":"invitationTentative","emotion":"neutral","text":""},
{"kind":"invitationAccept","emotion":"warm","text":""},
{"kind":"invitationDecline","emotion":"grateful","text":""}
]}
"""
let variants = try XCTUnwrap(
AIReplyVariantParser.parse(
valid,
variantSet: .invitation
)
)
XCTAssertEqual(variants.map(\.kind), AIReplyVariantSet.invitation.kinds)
XCTAssertNil(AIReplyVariantParser.parse(valid, variantSet: .generic))
XCTAssertNil(
AIReplyVariantParser.parseOrFallback(
"好呀,到时见。",
variantSet: .invitation
)
)
}
func testIntentScenesAlwaysGenerateChoicesWhenPreferenceIsOff() {
for scene in [
AIClipboardReplyScene.invitation,
.task,
.blessing,
.clarification
] {
XCTAssertTrue(
AIReplyVariantSet.shouldGenerate(
multipleRepliesEnabled: false,
scene: scene
)
)
}
XCTAssertFalse(
AIReplyVariantSet.shouldGenerate(
multipleRepliesEnabled: false,
scene: .complaint
)
)
XCTAssertFalse(
AIReplyVariantSet.shouldGenerate(
multipleRepliesEnabled: false,
scene: nil
)
)
}
func testIntentChoicePresentationUsesFixedLocalMeaning() {
XCTAssertEqual(
AIReplyVariantSet.task.kinds.map(\.titleKey),
[
"keyboard.ai.replyVariant.taskAcknowledge",
"keyboard.ai.replyVariant.taskClarify",
"keyboard.ai.replyVariant.taskNegotiate"
]
)
XCTAssertEqual(
AIReplyVariantSet.invitation.kinds.map(\.systemImage),
["checkmark.circle.fill", "hand.raised.fill", "clock.fill"]
)
XCTAssertTrue(AIReplyVariantSet.generic.kinds.allSatisfy(\.usesEmotionIcon))
XCTAssertTrue(
AIReplyVariantSet.invitation.kinds.allSatisfy {
!$0.usesEmotionIcon
}
)
}
func testEmotionMapsOnlyToLocalSFSymbolAllowlist() {
XCTAssertEqual(
AIReplyVariant.Emotion.celebratory.systemImage(fallback: .ordinary),