- Migrate Suite4-10, SmokeTests, NavigationCriticalPathTests to AuthenticatedTestCase with seeded admin account and real backend login - Add 34 accessibility identifiers across 11 app views (task completion, profile, notifications, theme, join residence, manage users, forms) - Create FeatureCoverageTests (14 tests) covering previously untested features: profile edit, theme selection, notification prefs, task completion, manage users, join residence, task templates - Create MultiUserSharingTests (18 API tests) and MultiUserSharingUITests (8 XCUI tests) for full cross-user residence sharing lifecycle - Add cleanup infrastructure: SuiteZZ_CleanupTests auto-wipes test data after runs, cleanup_test_data.sh script for manual reset via admin API - Add share code API methods to TestAccountAPIClient (generateShareCode, joinWithCode, getShareCode, listResidenceUsers, removeUser) - Fix app bugs found by tests: - ResidencesListView join callback now uses forceRefresh:true - APILayer invalidates task cache when residence count changes - AllTasksView auto-reloads tasks when residence list changes - Fix test quality: keyboard focus waits, Save/Add button label matching, Documents tab label (Docs), remove API verification from UI tests - DataLayerTests and PasswordResetTests now verify through UI, not API calls Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
158 lines
5.7 KiB
Swift
158 lines
5.7 KiB
Swift
import XCTest
|
|
|
|
/// Critical path tests for core navigation.
|
|
///
|
|
/// Validates tab bar navigation, settings access, and screen transitions.
|
|
/// Requires a logged-in user. Zero sleep() calls — all waits are condition-based.
|
|
final class NavigationCriticalPathTests: AuthenticatedTestCase {
|
|
override var useSeededAccount: Bool { true }
|
|
|
|
// MARK: - Tab Navigation
|
|
|
|
func testAllTabsExist() {
|
|
let tabBar = app.tabBars.firstMatch
|
|
guard tabBar.waitForExistence(timeout: defaultTimeout) else {
|
|
XCTFail("Main screen did not appear")
|
|
return
|
|
}
|
|
|
|
let residencesTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch
|
|
let tasksTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Tasks'")).firstMatch
|
|
let contractorsTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Contractors'")).firstMatch
|
|
let documentsTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Doc'")).firstMatch
|
|
|
|
XCTAssertTrue(residencesTab.exists, "Residences tab should exist")
|
|
XCTAssertTrue(tasksTab.exists, "Tasks tab should exist")
|
|
XCTAssertTrue(contractorsTab.exists, "Contractors tab should exist")
|
|
XCTAssertTrue(documentsTab.exists, "Documents tab should exist")
|
|
}
|
|
|
|
func testNavigateToTasksTab() {
|
|
let tabBar = app.tabBars.firstMatch
|
|
guard tabBar.waitForExistence(timeout: defaultTimeout) else {
|
|
XCTFail("Main screen did not appear")
|
|
return
|
|
}
|
|
|
|
navigateToTasks()
|
|
let tasksTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Tasks'")).firstMatch
|
|
XCTAssertTrue(tasksTab.isSelected, "Tasks tab should be selected")
|
|
}
|
|
|
|
func testNavigateToContractorsTab() {
|
|
let tabBar = app.tabBars.firstMatch
|
|
guard tabBar.waitForExistence(timeout: defaultTimeout) else {
|
|
XCTFail("Main screen did not appear")
|
|
return
|
|
}
|
|
|
|
navigateToContractors()
|
|
let contractorsTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Contractors'")).firstMatch
|
|
XCTAssertTrue(contractorsTab.isSelected, "Contractors tab should be selected")
|
|
}
|
|
|
|
func testNavigateToDocumentsTab() {
|
|
let tabBar = app.tabBars.firstMatch
|
|
guard tabBar.waitForExistence(timeout: defaultTimeout) else {
|
|
XCTFail("Main screen did not appear")
|
|
return
|
|
}
|
|
|
|
navigateToDocuments()
|
|
let documentsTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Doc'")).firstMatch
|
|
XCTAssertTrue(documentsTab.isSelected, "Documents tab should be selected")
|
|
}
|
|
|
|
func testNavigateBackToResidencesTab() {
|
|
let tabBar = app.tabBars.firstMatch
|
|
guard tabBar.waitForExistence(timeout: defaultTimeout) else {
|
|
XCTFail("Main screen did not appear")
|
|
return
|
|
}
|
|
|
|
navigateToDocuments()
|
|
navigateToResidences()
|
|
let residencesTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch
|
|
XCTAssertTrue(residencesTab.isSelected, "Residences tab should be selected")
|
|
}
|
|
|
|
// MARK: - Settings Access
|
|
|
|
func testSettingsButtonExists() {
|
|
let tabBar = app.tabBars.firstMatch
|
|
guard tabBar.waitForExistence(timeout: defaultTimeout) else {
|
|
XCTFail("Main screen did not appear")
|
|
return
|
|
}
|
|
|
|
navigateToResidences()
|
|
let settingsButton = app.buttons[AccessibilityIdentifiers.Navigation.settingsButton]
|
|
XCTAssertTrue(
|
|
settingsButton.waitForExistence(timeout: 5),
|
|
"Settings button should exist on Residences screen"
|
|
)
|
|
}
|
|
|
|
// MARK: - Add Buttons
|
|
|
|
func testResidenceAddButtonExists() {
|
|
let tabBar = app.tabBars.firstMatch
|
|
guard tabBar.waitForExistence(timeout: defaultTimeout) else {
|
|
XCTFail("Main screen did not appear")
|
|
return
|
|
}
|
|
|
|
navigateToResidences()
|
|
let addButton = app.buttons[AccessibilityIdentifiers.Residence.addButton].firstMatch
|
|
XCTAssertTrue(
|
|
addButton.waitForExistence(timeout: 5),
|
|
"Residence add button should exist"
|
|
)
|
|
}
|
|
|
|
func testTaskAddButtonExists() {
|
|
let tabBar = app.tabBars.firstMatch
|
|
guard tabBar.waitForExistence(timeout: defaultTimeout) else {
|
|
XCTFail("Main screen did not appear")
|
|
return
|
|
}
|
|
|
|
navigateToTasks()
|
|
let addButton = app.buttons[AccessibilityIdentifiers.Task.addButton].firstMatch
|
|
XCTAssertTrue(
|
|
addButton.waitForExistence(timeout: 5),
|
|
"Task add button should exist"
|
|
)
|
|
}
|
|
|
|
func testContractorAddButtonExists() {
|
|
let tabBar = app.tabBars.firstMatch
|
|
guard tabBar.waitForExistence(timeout: defaultTimeout) else {
|
|
XCTFail("Main screen did not appear")
|
|
return
|
|
}
|
|
|
|
navigateToContractors()
|
|
let addButton = app.buttons[AccessibilityIdentifiers.Contractor.addButton].firstMatch
|
|
XCTAssertTrue(
|
|
addButton.waitForExistence(timeout: 5),
|
|
"Contractor add button should exist"
|
|
)
|
|
}
|
|
|
|
func testDocumentAddButtonExists() {
|
|
let tabBar = app.tabBars.firstMatch
|
|
guard tabBar.waitForExistence(timeout: defaultTimeout) else {
|
|
XCTFail("Main screen did not appear")
|
|
return
|
|
}
|
|
|
|
navigateToDocuments()
|
|
let addButton = app.buttons[AccessibilityIdentifiers.Document.addButton].firstMatch
|
|
XCTAssertTrue(
|
|
addButton.waitForExistence(timeout: 5),
|
|
"Document add button should exist"
|
|
)
|
|
}
|
|
}
|