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 {
|
override func setUpWithError() throws {
|
||||||
guard TestAccountAPIClient.isBackendReachable() else {
|
guard TestAccountAPIClient.isBackendReachable() else {
|
||||||
throw XCTSkip("Backend not reachable at \(TestAccountAPIClient.baseURL)")
|
throw XCTSkip("Backend not reachable at \(TestAccountAPIClient.baseURL)")
|
||||||
@@ -41,27 +58,27 @@ class AuthenticatedUITestCase: BaseUITestCase {
|
|||||||
|
|
||||||
try super.setUpWithError()
|
try super.setUpWithError()
|
||||||
|
|
||||||
// If already logged in (tab bar visible), skip the login flow
|
|
||||||
let tabBar = app.tabBars.firstMatch
|
let tabBar = app.tabBars.firstMatch
|
||||||
if tabBar.waitForExistence(timeout: defaultTimeout) {
|
let alreadyLoggedIn = 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not logged in — do the full login flow
|
// 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)
|
UITestHelpers.ensureLoggedOut(app: app)
|
||||||
loginToMainApp()
|
loginToMainApp()
|
||||||
|
}
|
||||||
|
// (When `forceFreshLoginPerTest == false` AND we're already
|
||||||
|
// logged in, fall through with the existing session.)
|
||||||
|
|
||||||
if needsAPISession {
|
if needsAPISession {
|
||||||
guard let apiSession = TestAccountManager.loginSeededAccount(
|
guard let apiSession = TestAccountManager.loginSeededAccount(
|
||||||
|
|||||||
Reference in New Issue
Block a user