// // BaseUITestCase.swift // Tests iOS // // Base class for all UI tests. Handles launch arguments, // state reset, and screenshot capture on failure. // import XCTest class BaseUITestCase: XCTestCase { var app: XCUIApplication! // MARK: - Configuration (override in subclasses) /// Fixture to seed. Override to use a specific data set. var seedFixture: String? { nil } /// Whether to bypass the subscription paywall. Default: true. var bypassSubscription: Bool { true } /// Whether to skip onboarding. Default: true. var skipOnboarding: Bool { true } /// Whether to force the trial to be expired. Default: false. var expireTrial: Bool { false } // MARK: - Lifecycle override func setUp() { super.setUp() continueAfterFailure = false app = XCUIApplication() app.launchArguments = buildLaunchArguments() app.launchEnvironment = buildLaunchEnvironment() app.launch() } override func tearDown() { if let failure = testRun?.failureCount, failure > 0 { captureScreenshot(name: "FAILURE-\(name)") } app = nil super.tearDown() } // MARK: - Launch Configuration private func buildLaunchArguments() -> [String] { var args = ["--ui-testing", "--reset-state", "--disable-animations"] if bypassSubscription { args.append("--bypass-subscription") } if skipOnboarding { args.append("--skip-onboarding") } if expireTrial { args.append("--expire-trial") } return args } private func buildLaunchEnvironment() -> [String: String] { var env = [String: String]() if let fixture = seedFixture { env["UI_TEST_FIXTURE"] = fixture } return env } // MARK: - Screenshots func captureScreenshot(name: String) { let screenshot = XCTAttachment(screenshot: app.screenshot()) screenshot.name = name screenshot.lifetime = .keepAlways add(screenshot) } }