新增完整 UI Test 回归套件,并完善启动隔离逻辑。
按模块拆分 XCUITest 用例与 Support 基础设施,UI Test 运行时跳过推送与排队 WebSocket,并将 Podfile 最低版本对齐 iOS 16。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -38,6 +38,12 @@ App 模块负责应用入口、根视图切换、全局状态注入、主导航
|
||||
10. 明确 token 失效时清空 token 和账号快照,回到登录页。
|
||||
11. 普通网络失败时保留本地登录态,使用账号快照进入主界面。
|
||||
|
||||
## UI Test 启动约定
|
||||
|
||||
- `AppUITestLaunchState` 在收到 `-suixinkan-ui-tests` 时跳过推送注册和排队 WebSocket,避免系统弹窗干扰自动化。
|
||||
- `-suixinkan-ui-tests-reset-state` 用于冷启动清理 Keychain 与 UserDefaults。
|
||||
- 详细运行方式见 `suixinkanUITests/README.md`。
|
||||
|
||||
## 登录和退出
|
||||
|
||||
登录完成由 `AuthSessionCoordinator.completeLogin` 统一处理:
|
||||
|
||||
@ -7,10 +7,19 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
/// UI 测试启动状态清理,仅在测试进程显式传入启动参数时执行。
|
||||
/// UI 测试启动状态,仅在测试进程显式传入启动参数时生效。
|
||||
enum AppUITestLaunchState {
|
||||
/// UI Test 主开关,测试进程统一传入。
|
||||
static let uiTestsArgument = "-suixinkan-ui-tests"
|
||||
/// 冷启动前清理本地登录缓存。
|
||||
static let resetArgument = "-suixinkan-ui-tests-reset-state"
|
||||
|
||||
/// 当前进程是否由 XCUITest 启动。
|
||||
static var isRunningUITests: Bool {
|
||||
ProcessInfo.processInfo.arguments.contains(uiTestsArgument)
|
||||
}
|
||||
|
||||
/// 按需在冷启动时清理 token、账号快照和偏好设置。
|
||||
static func resetIfNeeded(arguments: [String] = ProcessInfo.processInfo.arguments) {
|
||||
guard arguments.contains(resetArgument) else { return }
|
||||
|
||||
|
||||
@ -146,7 +146,7 @@ struct RootView: View {
|
||||
toastCenter: toastCenter
|
||||
)
|
||||
}
|
||||
if appSession.isLoggedIn {
|
||||
if appSession.isLoggedIn, !AppUITestLaunchState.isRunningUITests {
|
||||
PushNotificationManager.shared.requestAuthorizationAndRegister()
|
||||
}
|
||||
}
|
||||
@ -161,6 +161,7 @@ struct RootView: View {
|
||||
)
|
||||
}
|
||||
.onChange(of: scenePhase) { newPhase in
|
||||
guard !AppUITestLaunchState.isRunningUITests else { return }
|
||||
if appSession.isLoggedIn {
|
||||
scenicQueueRuntime.update(
|
||||
api: scenicQueueAPI,
|
||||
@ -173,6 +174,7 @@ struct RootView: View {
|
||||
}
|
||||
}
|
||||
.onChange(of: accountContext.currentScenic?.id) { _ in
|
||||
guard !AppUITestLaunchState.isRunningUITests else { return }
|
||||
if appSession.isLoggedIn {
|
||||
scenicQueueRuntime.update(
|
||||
api: scenicQueueAPI,
|
||||
@ -185,7 +187,9 @@ struct RootView: View {
|
||||
.onChange(of: appSession.phase) { phase in
|
||||
switch phase {
|
||||
case .loggedIn:
|
||||
PushNotificationManager.shared.requestAuthorizationAndRegister()
|
||||
if !AppUITestLaunchState.isRunningUITests {
|
||||
PushNotificationManager.shared.requestAuthorizationAndRegister()
|
||||
}
|
||||
case .loggedOut:
|
||||
accountContext.reset()
|
||||
permissionContext.reset()
|
||||
|
||||
Reference in New Issue
Block a user