Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d5041492a9 | |||
| ec5d93efab |
@@ -34,6 +34,23 @@ class AuthenticatedUITestCase: BaseUITestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/// When `true`, every test in the suite forces a logout → login cycle
|
||||
/// in `setUp`, guaranteeing a freshly-issued auth token on each run.
|
||||
///
|
||||
/// Default is `false`: tests reuse the existing logged-in session
|
||||
/// from the previous test in the same suite — much faster (one login
|
||||
/// per suite, not one per test) and resilient to suites where the
|
||||
/// current screen has no logout affordance (`UITestHelpers.ensureLoggedOut`
|
||||
/// times out → the test fails before its body runs).
|
||||
///
|
||||
/// Override to `true` in suites that have observed transient
|
||||
/// `Invalid token` 401s on POST/PATCH while reads continue to work.
|
||||
/// The recipe was added after a 2026-05 incident where the API
|
||||
/// container was rebuilt mid-suite and in-memory tokens went stale.
|
||||
/// In normal CI runs against a stable API + freshly-erased simulator,
|
||||
/// session reuse is the correct default.
|
||||
var forceFreshLoginPerTest: Bool { false }
|
||||
|
||||
override func setUpWithError() throws {
|
||||
guard TestAccountAPIClient.isBackendReachable() else {
|
||||
throw XCTSkip("Backend not reachable at \(TestAccountAPIClient.baseURL)")
|
||||
@@ -41,27 +58,27 @@ class AuthenticatedUITestCase: BaseUITestCase {
|
||||
|
||||
try super.setUpWithError()
|
||||
|
||||
// If already logged in (tab bar visible), skip the login flow
|
||||
let tabBar = app.tabBars.firstMatch
|
||||
if tabBar.waitForExistence(timeout: defaultTimeout) {
|
||||
// Already logged in — just set up API session if needed
|
||||
if needsAPISession {
|
||||
guard let apiSession = TestAccountManager.loginSeededAccount(
|
||||
username: apiCredentials.username,
|
||||
password: apiCredentials.password
|
||||
) else {
|
||||
XCTFail("Could not login API account '\(apiCredentials.username)'")
|
||||
return
|
||||
}
|
||||
session = apiSession
|
||||
cleaner = TestDataCleaner(token: apiSession.token)
|
||||
}
|
||||
return
|
||||
}
|
||||
let alreadyLoggedIn = tabBar.waitForExistence(timeout: defaultTimeout)
|
||||
|
||||
// Not logged in — do the full login flow
|
||||
UITestHelpers.ensureLoggedOut(app: app)
|
||||
loginToMainApp()
|
||||
// Force-fresh path: log out (if needed) and re-authenticate per
|
||||
// test so every test starts with a freshly-issued JWT. Catches
|
||||
// server-side token invalidation that would otherwise surface
|
||||
// mid-suite as opaque 401s on the first mutation call.
|
||||
if forceFreshLoginPerTest {
|
||||
if alreadyLoggedIn {
|
||||
UITestHelpers.ensureLoggedOut(app: app)
|
||||
} else {
|
||||
UITestHelpers.ensureLoggedOut(app: app)
|
||||
}
|
||||
loginToMainApp()
|
||||
} else if !alreadyLoggedIn {
|
||||
// Legacy session-reuse path: only log in when not already in.
|
||||
UITestHelpers.ensureLoggedOut(app: app)
|
||||
loginToMainApp()
|
||||
}
|
||||
// (When `forceFreshLoginPerTest == false` AND we're already
|
||||
// logged in, fall through with the existing session.)
|
||||
|
||||
if needsAPISession {
|
||||
guard let apiSession = TestAccountManager.loginSeededAccount(
|
||||
|
||||
Reference in New Issue
Block a user