补充 Auth/Tasks/ScenicPermission/Live 单元测试,并完善 UI Test 登录与会话稳定性。
移除 LoginViewModel 硬编码账号,扩展登录流程测试覆盖;调整 ZLoginSmokeUITests 执行顺序与路由直达逻辑,避免清空 Keychain 影响其它用例。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -18,6 +18,8 @@ enum LoginFlow {
|
||||
) {
|
||||
guard app.isOnLoginScreen else { return }
|
||||
|
||||
app.application.activate()
|
||||
app.waitForGlobalLoadingToDisappear()
|
||||
fillLoginForm(app: app, credentials: credentials)
|
||||
submitLogin(app: app)
|
||||
handleAccountSelectionIfNeeded(app: app, credentials: credentials)
|
||||
@ -34,17 +36,21 @@ enum LoginFlow {
|
||||
/// 填写登录表单并勾选协议。
|
||||
static func fillLoginForm(app: SuixinkanApp, credentials: UITestCredentials) {
|
||||
let usernameField = app.application.textFields["login.username"]
|
||||
XCTAssertTrue(usernameField.waitForExistence(timeout: 8))
|
||||
usernameField.tap()
|
||||
usernameField.clearAndType(credentials.phone)
|
||||
XCTAssertTrue(usernameField.waitForExistence(timeout: 12))
|
||||
|
||||
let currentPhone = usernameField.value as? String
|
||||
if currentPhone != credentials.phone {
|
||||
tapWhenReady(usernameField)
|
||||
usernameField.clearAndType(credentials.phone)
|
||||
}
|
||||
|
||||
let passwordField = preferredPasswordField(in: app.application)
|
||||
XCTAssertTrue(passwordField.waitForExistence(timeout: 4))
|
||||
passwordField.tap()
|
||||
tapWhenReady(passwordField)
|
||||
passwordField.clearAndType(credentials.password)
|
||||
|
||||
let privacyToggle = app.application.buttons["login.privacy"]
|
||||
if privacyToggle.exists {
|
||||
if privacyToggle.exists, privacyToggle.isHittable {
|
||||
privacyToggle.tap()
|
||||
}
|
||||
}
|
||||
@ -53,7 +59,7 @@ enum LoginFlow {
|
||||
static func submitLogin(app: SuixinkanApp) {
|
||||
let submitButton = app.application.buttons["login.submit"]
|
||||
XCTAssertTrue(submitButton.waitForExistence(timeout: 4))
|
||||
submitButton.tap()
|
||||
tapWhenReady(submitButton)
|
||||
app.waitForGlobalLoadingToDisappear()
|
||||
}
|
||||
|
||||
@ -86,12 +92,26 @@ enum LoginFlow {
|
||||
}
|
||||
return app.textFields["login.password"]
|
||||
}
|
||||
|
||||
/// 等待元素可点后点击,不可点时退化为坐标点击。
|
||||
private static func tapWhenReady(_ element: XCUIElement) {
|
||||
let deadline = Date().addingTimeInterval(8)
|
||||
while Date() < deadline {
|
||||
if element.isHittable {
|
||||
element.tap()
|
||||
return
|
||||
}
|
||||
RunLoop.current.run(until: Date().addingTimeInterval(0.2))
|
||||
}
|
||||
|
||||
element.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
|
||||
}
|
||||
}
|
||||
|
||||
private extension XCUIElement {
|
||||
/// 清空并重新输入文本。
|
||||
func clearAndType(_ text: String) {
|
||||
guard let currentValue = value as? String else {
|
||||
guard let currentValue = value as? String, !currentValue.isEmpty else {
|
||||
typeText(text)
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user