iOS: absolutely center empty states across every tab
Android UI Tests / ui-tests (push) Has been cancelled

Anchor the empty-state icon/text boundary at the exact vertical center
in the shared OrganicEmptyScreen: the icon's bottom sits 8pt above center
and the text's top 8pt below, so the 16pt gap straddles 50% Y regardless
of icon size or title/subtitle length. Previously the block-center was
centered, so longer copy drifted the icon (~1.7% spread across tabs);
boundary spread is now ~0.1% (pixel-identical on all four tabs).

Supporting changes so each tab renders the empty state alone (full
content area, consistent nav-bar height):
- Tasks: keep toolbar buttons present (disabled) when empty so the inline
  nav bar doesn't collapse and shift content up
- Contractors/Documents: hide search/filter chrome when truly empty
- Residences: restore original copy + frame-fill

Adds EmptyStateScreenshotUITests as a regression guard that captures the
empty state of all four tabs for a fresh verified no-data user.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey T
2026-06-06 12:08:54 -05:00
parent c0032ab7e1
commit 713c8d9cbb
6 changed files with 297 additions and 166 deletions
@@ -0,0 +1,28 @@
import XCTest
/// Exploratory: capture the empty-state of every main tab for a FRESH, verified,
/// no-data user (no residence/task/contractor/document). Used to compare empty-
/// state vertical/horizontal centering across tabs. Not part of the regular run.
final class EmptyStateScreenshotUITests: AuthenticatedUITestCase {
// Fresh verified account, NO preconditions -> every tab is empty.
// (requiresResidence stays false; nothing is seeded.)
func test_captureAllTabEmptyStates() {
let tabs: [(name: String, nav: () -> Void)] = [
("01-Residences", { self.navigateToResidences() }),
("02-Tasks", { self.navigateToTasks() }),
("03-Contractors",{ self.navigateToContractors() }),
("04-Documents", { self.navigateToDocuments() }),
]
for tab in tabs {
tab.nav()
// Let the screen + any empty-state render fully settle.
RunLoop.current.run(until: Date().addingTimeInterval(2.0))
let shot = XCTAttachment(screenshot: app.screenshot())
shot.name = "EmptyState-\(tab.name)"
shot.lifetime = .keepAlways
add(shot)
}
}
}