import XCTest /// Walks the adaptive layout (tab bar / sidebar, split views, inspector) and /// attaches a screenshot per step. Run on a compact device (iPhone) and on a /// regular×regular one (iPad mini ≈ iPhone Duo inner screen) to compare. final class DuoLayoutUITests: XCTestCase { override func setUpWithError() throws { continueAfterFailure = true } private func snap(_ app: XCUIApplication, _ name: String) { let shot = XCTAttachment(screenshot: app.screenshot()) shot.name = name shot.lifetime = .keepAlways add(shot) } /// Tab bar button on iPhone, top tab bar / sidebar row on iPad. private func openTab(_ app: XCUIApplication, _ title: String) { let tabBar = app.tabBars.firstMatch if tabBar.exists && tabBar.buttons[title].exists && tabBar.buttons[title].isHittable { tabBar.buttons[title].tap() } else if app.buttons[title].firstMatch.waitForExistence(timeout: 3) { app.buttons[title].firstMatch.tap() } else if app.staticTexts[title].firstMatch.waitForExistence(timeout: 3) { app.staticTexts[title].firstMatch.tap() } Thread.sleep(forTimeInterval: 1.5) } func testAdaptiveLayoutWalkthrough() throws { let app = XCUIApplication() app.launchArguments = ["--screenshots"] app.launch() Thread.sleep(forTimeInterval: 4.0) let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") let denyButton = springboard.alerts.buttons["Don't Allow"] if denyButton.waitForExistence(timeout: 8) { denyButton.tap() Thread.sleep(forTimeInterval: 1.0) } snap(app, "01_dashboard") // Quick Update: inspector column in regular width, sheet in compact. let quickUpdate = app.buttons["dashboard.quickUpdate"].firstMatch if quickUpdate.waitForExistence(timeout: 3) { quickUpdate.tap() Thread.sleep(forTimeInterval: 2.0) snap(app, "02_quick_update_inspector") let cancel = app.buttons["Cancel"].firstMatch XCTAssertTrue(cancel.waitForExistence(timeout: 3), "Quick Update cancel button missing") cancel.tap() Thread.sleep(forTimeInterval: 1.5) XCTAssertFalse(app.buttons["Cancel"].firstMatch.exists, "Quick Update did not dismiss") snap(app, "03_dashboard_after_cancel") } else { XCTFail("Quick Update button not found") } openTab(app, "Sources") snap(app, "04_sources") let sourceCells = app.cells if sourceCells.count > 2 { sourceCells.element(boundBy: 2).tap() Thread.sleep(forTimeInterval: 2.0) snap(app, "05_source_detail") } openTab(app, "Charts") snap(app, "06_charts") openTab(app, "Journal") snap(app, "07_journal") let journalCells = app.cells if journalCells.count > 1 { journalCells.element(boundBy: 1).tap() Thread.sleep(forTimeInterval: 2.0) snap(app, "08_journal_detail") } openTab(app, "Settings") snap(app, "09_settings") // Landscape: the Duo inner screen is regular×regular in both orientations. XCUIDevice.shared.orientation = .landscapeLeft Thread.sleep(forTimeInterval: 2.0) openTab(app, "Home") snap(app, "10_dashboard_landscape") openTab(app, "Charts") snap(app, "11_charts_landscape") XCUIDevice.shared.orientation = .portrait } }