test(uitests): drain accumulated cart once per class before checkout tests

The cart is on-device state (CartState/SessionStateStore), not purely
server-side - it survives app relaunches on the same simulator and has
been accumulating real quantities across every manual and automated run
against the 'MARIBA' test store, with no reset in between. No one-tap
'empty cart' UI action exists; the app's only full-clear path (the
'Trocar de loja?' alert's 'Limpar carrinho e adicionar') only fires when
switching to a genuinely different store, which this suite never does.

Added CartCheckoutFlowTests.setUp() (class) to drain the cart via its
own per-item 'minus' control in a capped loop before this class's tests
run, once per class rather than once per test, so every run starts from
a known-empty cart.

See decisions/2026-09-11-ui-test-shared-login-session.md follow-up.
This commit is contained in:
2026-09-11 10:04:25 -03:00
parent 84be24f274
commit d06e5013a8

View File

@@ -6,6 +6,45 @@ import XCTest
/// so Home shows a real store list - see
/// decisions/2026-08-06-ui-test-account-and-app-attest-bypass.md.
final class CartCheckoutFlowTests: XCTestCase {
/// The cart is on-device state (`CartState`/`SessionStateStore`, see
/// `AppState.swift`), not server-side - it persists across app
/// relaunches on this simulator just like the login session (see
/// decisions/2026-09-11-ui-test-shared-login-session.md), and keeps
/// accumulating real quantities across every manual and automated run
/// against the "MARIBA" test store. There's no direct "empty cart" UI
/// action - the "Trocar de loja?" alert's "Limpar carrinho e
/// adicionar" (`StoreDetailView.swift`) only fires for a genuinely
/// different store (`shouldAskForStoreSwitch`,
/// `StoreDetailView+Logic.swift`), which this suite never triggers
/// since every test targets the same store. So: drain the cart via
/// its own per-item "minus" control, once per class (not once per
/// test - each drain can take several taps), so every run starts from
/// a known-empty cart instead of an ever-growing one.
override class func setUp() {
super.setUp()
let app = XCUIApplication()
app.launch()
app.ensureLoggedIn()
let cartTab = app.images.matching(identifier: "cart.fill").firstMatch
guard cartTab.waitForExistence(timeout: 10) else { return }
cartTab.tap()
guard app.staticTexts["Meu Carrinho"].waitForExistence(timeout: 10) else { return }
// No "set quantity" input exists in CartView - only per-tap
// increment/decrement - so draining is inherently one tap per
// unit. Capped rather than unbounded so a genuinely stuck cart
// fails fast instead of hanging the whole class.
let minusButton = app.images.matching(identifier: "minus").firstMatch
var remainingTaps = 500
while app.staticTexts["Seu carrinho está vazio"].exists == false, remainingTaps > 0 {
guard minusButton.waitForExistence(timeout: 3) else { break }
minusButton.tap()
usleep(150_000)
remainingTaps -= 1
}
}
override func setUpWithError() throws {
continueAfterFailure = false
}