Tests: corrige 3 tests desfasados y añade recorrido UI del layout adaptativo

- ReviewPromptServiceTests: la regla vigente pide 2 check-ins, no 3.
- MonthlyCheckInViewTests: el día 1 cae en el periodo de gracia (20 días);
  usar el día 25 para etiquetar febrero.
- SettingsViewModelTests: isPremium llega por receive(on: main); dar una
  vuelta de run loop antes de actuar.
- DuoLayoutUITests: recorre tabs, split views e inspector con capturas
  (ejecutar en iPhone 17 Pro y iPad mini). ScreenshotMode oculta los tips de
  TipKit; identificador de accesibilidad en el botón de Quick Update.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F1u4K16xy7eQVtgsYNZ9Vn
This commit is contained in:
alexandrev-tibco
2026-09-16 15:13:10 +02:00
parent 6774d76146
commit 171023a411
6 changed files with 108 additions and 2 deletions
@@ -0,0 +1,96 @@
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
}
}