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:
@@ -160,6 +160,16 @@ final class AssistantKeyboardUITests: XCTestCase {
|
||||
XCTAssertFalse(element("assistant.skills.pager", in: app).exists)
|
||||
}
|
||||
|
||||
func testReliableSemanticResultShowsCompactBadge() {
|
||||
let app = launch(scenario: "semanticBadge")
|
||||
let badge = requiredElement("assistant.semantic.badge", in: app)
|
||||
let mic = requiredElement("assistant.mic.idle", in: app)
|
||||
|
||||
XCTAssertTrue(badge.label.contains("Weather") || badge.label.contains("天气"))
|
||||
XCTAssertLessThan(badge.frame.height, mic.frame.height)
|
||||
XCTAssertTrue(element("assistant.clipboard.dismiss", in: app).exists)
|
||||
}
|
||||
|
||||
func testSearchFieldShowsEnabledSearchAction() {
|
||||
let app = launch(scenario: "search")
|
||||
let search = requiredElement("assistant.action.search", in: app)
|
||||
|
||||
@@ -1,29 +1,164 @@
|
||||
import XCTest
|
||||
|
||||
final class PolishStylesGenerationUITests: XCTestCase {
|
||||
func testTestBuildCanGenerateWithoutPersonalCorpus() {
|
||||
continueAfterFailure = false
|
||||
let app = launchServiceHarness(
|
||||
additionalArgument: "--polish-styles-service-ui-test-no-corpus"
|
||||
)
|
||||
|
||||
XCTAssertTrue(
|
||||
app.staticTexts[
|
||||
"Test build: 2,500-character limit disabled"
|
||||
]
|
||||
.waitForExistence(timeout: 5)
|
||||
)
|
||||
let generate = app.buttons["polishStyles.learn.generate"]
|
||||
XCTAssertTrue(generate.exists)
|
||||
XCTAssertTrue(generate.isEnabled)
|
||||
}
|
||||
|
||||
func testGeneratedStyleReviewAndSaveFlow() {
|
||||
continueAfterFailure = false
|
||||
let app = XCUIApplication()
|
||||
app.launchArguments = [
|
||||
"--polish-styles-screenshot",
|
||||
"--polish-styles-generation-demo"
|
||||
]
|
||||
app.launch()
|
||||
let app = launchServiceHarness()
|
||||
|
||||
let generate = app.buttons["polishStyles.learn.generate"]
|
||||
XCTAssertTrue(generate.waitForExistence(timeout: 5))
|
||||
Thread.sleep(forTimeInterval: 0.8)
|
||||
generate.tap()
|
||||
|
||||
let save = app.buttons["polishStyles.editor.save"]
|
||||
XCTAssertTrue(save.waitForExistence(timeout: 5))
|
||||
Thread.sleep(forTimeInterval: 1.2)
|
||||
XCTAssertTrue(save.waitForExistence(timeout: 8))
|
||||
let promptEditor = app.textViews["polishStyles.editor.prompt"]
|
||||
XCTAssertTrue(promptEditor.waitForExistence(timeout: 2))
|
||||
XCTAssertTrue(
|
||||
(promptEditor.value as? String)?.contains("natural, direct voice") == true,
|
||||
"The real learning service must pass the scripted synthesis into review"
|
||||
)
|
||||
save.tap()
|
||||
|
||||
let learnedCard = app.descendants(matching: .any)[
|
||||
"polishStyles.learnedStyle.card"
|
||||
]
|
||||
XCTAssertTrue(learnedCard.waitForExistence(timeout: 5))
|
||||
Thread.sleep(forTimeInterval: 1.2)
|
||||
XCTAssertTrue(app.staticTexts["Confidence: 86%"].exists)
|
||||
}
|
||||
|
||||
func testInsufficientEvidenceIsDisclosedDuringReviewAndAfterSave() {
|
||||
continueAfterFailure = false
|
||||
let app = launchServiceHarness(usesInsufficientEvidence: true)
|
||||
|
||||
let generate = app.buttons["polishStyles.learn.generate"]
|
||||
XCTAssertTrue(generate.waitForExistence(timeout: 5))
|
||||
generate.tap()
|
||||
|
||||
let warning = app.staticTexts[
|
||||
"Low confidence. The prompt was generated from limited evidence; please review it."
|
||||
]
|
||||
XCTAssertTrue(warning.waitForExistence(timeout: 8))
|
||||
XCTAssertTrue(app.staticTexts["Confidence: 20%"].exists)
|
||||
|
||||
let save = app.buttons["polishStyles.editor.save"]
|
||||
XCTAssertTrue(save.exists)
|
||||
save.tap()
|
||||
|
||||
let learnedCard = app.descendants(matching: .any)[
|
||||
"polishStyles.learnedStyle.card"
|
||||
]
|
||||
XCTAssertTrue(learnedCard.waitForExistence(timeout: 5))
|
||||
XCTAssertTrue(warning.waitForExistence(timeout: 2))
|
||||
}
|
||||
|
||||
func testRegenerationPreservesExistingStyleIdentityUntilSave() {
|
||||
continueAfterFailure = false
|
||||
let app = launchServiceHarness(
|
||||
additionalArgument: "--polish-styles-service-ui-test-regenerate"
|
||||
)
|
||||
let learnedCard = app.descendants(matching: .any)[
|
||||
"polishStyles.learnedStyle.card"
|
||||
]
|
||||
XCTAssertTrue(learnedCard.waitForExistence(timeout: 5))
|
||||
let regenerate = app.buttons["Regenerate"]
|
||||
XCTAssertTrue(regenerate.exists)
|
||||
let originalID = regenerate.value as? String
|
||||
XCTAssertFalse(originalID?.isEmpty ?? true)
|
||||
|
||||
regenerate.tap()
|
||||
let save = app.buttons["polishStyles.editor.save"]
|
||||
XCTAssertTrue(save.waitForExistence(timeout: 8))
|
||||
XCTAssertEqual(
|
||||
regenerate.value as? String,
|
||||
originalID,
|
||||
"The persisted style must remain unchanged while review is open"
|
||||
)
|
||||
save.tap()
|
||||
|
||||
XCTAssertTrue(learnedCard.waitForExistence(timeout: 5))
|
||||
XCTAssertEqual(
|
||||
app.buttons["Regenerate"].value as? String,
|
||||
originalID
|
||||
)
|
||||
}
|
||||
|
||||
func testSynthesisFailureKeepsExistingStyleUnchanged() {
|
||||
continueAfterFailure = false
|
||||
let app = launchServiceHarness(
|
||||
additionalArgument: "--polish-styles-service-ui-test-failure"
|
||||
)
|
||||
let learnedCard = app.descendants(matching: .any)[
|
||||
"polishStyles.learnedStyle.card"
|
||||
]
|
||||
XCTAssertTrue(learnedCard.waitForExistence(timeout: 5))
|
||||
let regenerate = app.buttons["Regenerate"]
|
||||
let originalID = regenerate.value as? String
|
||||
|
||||
regenerate.tap()
|
||||
XCTAssertTrue(
|
||||
app.staticTexts["Couldn’t Generate Style"].waitForExistence(timeout: 8)
|
||||
)
|
||||
XCTAssertEqual(regenerate.value as? String, originalID)
|
||||
XCTAssertFalse(app.buttons["polishStyles.editor.save"].exists)
|
||||
}
|
||||
|
||||
func testLeavingStyleScreenCancelsGenerationWithoutTimeoutAlert() {
|
||||
continueAfterFailure = false
|
||||
let app = launchServiceHarness(
|
||||
additionalArgument: "--polish-styles-service-ui-test-cancel"
|
||||
)
|
||||
let generate = app.buttons["polishStyles.learn.generate"]
|
||||
XCTAssertTrue(generate.waitForExistence(timeout: 5))
|
||||
generate.tap()
|
||||
|
||||
let leave = app.buttons["polishStyles.test.leave"]
|
||||
XCTAssertTrue(leave.exists)
|
||||
leave.tap()
|
||||
XCTAssertTrue(
|
||||
app.staticTexts["polishStyles.test.closed"].waitForExistence(timeout: 3)
|
||||
)
|
||||
XCTAssertTrue(
|
||||
app.staticTexts["polishStyles.test.cancelled"].waitForExistence(timeout: 3)
|
||||
)
|
||||
XCTAssertFalse(app.staticTexts["Couldn’t Generate Style"].exists)
|
||||
}
|
||||
|
||||
private func launchServiceHarness(
|
||||
usesInsufficientEvidence: Bool = false,
|
||||
additionalArgument: String? = nil
|
||||
) -> XCUIApplication {
|
||||
let app = XCUIApplication()
|
||||
app.launchArguments = [
|
||||
"--polish-styles-screenshot",
|
||||
"--polish-styles-service-ui-test",
|
||||
"--screenshot-lang=en"
|
||||
]
|
||||
if usesInsufficientEvidence {
|
||||
app.launchArguments.append(
|
||||
"--polish-styles-service-ui-test-insufficient"
|
||||
)
|
||||
}
|
||||
if let additionalArgument {
|
||||
app.launchArguments.append(additionalArgument)
|
||||
}
|
||||
app.launch()
|
||||
return app
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user