Phases 1-6 of fixes.md — closes all 13 issues from codex_issues_2.md re-validation: KMP Architecture: - Fix subscription purchase/restore response contract (VerificationResponse aligned) - Add feature benefits auth token + APILayer init flow - Remove ResidenceFormScreen direct API bypass (use APILayer) - Wire paywall purchase/restore to real SubscriptionApi calls iOS Platform: - Add iOS Keychain token storage via Swift KeychainHelper - Implement Google Sign-In via ASWebAuthenticationSession (GoogleSignInManager) - DocumentViewModelWrapper observes DataManager for auto-updates - Add missing accessibility identifiers (document, task columns, Google Sign-In) XCUITest Rewrite: - Rewrite test infrastructure: zero sleep() calls, accessibility ID lookups - Create AuthCriticalPathTests and NavigationCriticalPathTests - Delete 14 legacy brittle test files (Suite0-10, templates) - Fix CaseraTests module import (@testable import Casera) All platforms build clean. TEST BUILD SUCCEEDED. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
119 lines
4.1 KiB
Swift
119 lines
4.1 KiB
Swift
import XCTest
|
|
|
|
/// Smoke tests - run on every PR. Must complete in <2 minutes.
|
|
///
|
|
/// Tests that the app launches successfully, the auth screen renders correctly,
|
|
/// and core navigation is functional. These are the minimum-viability tests
|
|
/// that must pass before any PR can merge.
|
|
///
|
|
/// Zero sleep() calls — all waits are condition-based.
|
|
final class SmokeTests: XCTestCase {
|
|
var app: XCUIApplication!
|
|
|
|
override func setUp() {
|
|
super.setUp()
|
|
continueAfterFailure = false
|
|
app = TestLaunchConfig.launchApp()
|
|
}
|
|
|
|
override func tearDown() {
|
|
app = nil
|
|
super.tearDown()
|
|
}
|
|
|
|
// MARK: - App Launch
|
|
|
|
func testAppLaunches() {
|
|
// App should show either login screen or main tab view
|
|
let loginScreen = LoginScreen(app: app)
|
|
let mainScreen = MainTabScreen(app: app)
|
|
|
|
let loginAppeared = loginScreen.emailField.waitForExistence(timeout: 15)
|
|
let mainAppeared = mainScreen.residencesTab.waitForExistence(timeout: 5)
|
|
|
|
XCTAssertTrue(loginAppeared || mainAppeared, "App should show login or main screen on launch")
|
|
}
|
|
|
|
// MARK: - Login Screen Elements
|
|
|
|
func testLoginScreenElements() {
|
|
let login = LoginScreen(app: app)
|
|
guard login.emailField.waitForExistence(timeout: 15) else {
|
|
// Already logged in, skip this test
|
|
return
|
|
}
|
|
|
|
XCTAssertTrue(login.emailField.exists, "Email field should exist")
|
|
XCTAssertTrue(login.passwordField.exists, "Password field should exist")
|
|
XCTAssertTrue(login.loginButton.exists, "Login button should exist")
|
|
}
|
|
|
|
// MARK: - Login Flow
|
|
|
|
func testLoginWithExistingCredentials() {
|
|
let login = LoginScreen(app: app)
|
|
guard login.emailField.waitForExistence(timeout: 15) else {
|
|
// Already on main screen - verify tabs
|
|
let main = MainTabScreen(app: app)
|
|
XCTAssertTrue(main.isDisplayed, "Main tabs should be visible")
|
|
return
|
|
}
|
|
|
|
// Login with the known test user
|
|
let user = TestFixtures.TestUser.existing
|
|
login.login(email: user.email, password: user.password)
|
|
|
|
let main = MainTabScreen(app: app)
|
|
XCTAssertTrue(main.residencesTab.waitForExistence(timeout: 15), "Should navigate to main screen after login")
|
|
}
|
|
|
|
// MARK: - Tab Navigation
|
|
|
|
func testMainTabsExistAfterLogin() {
|
|
let login = LoginScreen(app: app)
|
|
if login.emailField.waitForExistence(timeout: 15) {
|
|
let user = TestFixtures.TestUser.existing
|
|
login.login(email: user.email, password: user.password)
|
|
}
|
|
|
|
let main = MainTabScreen(app: app)
|
|
guard main.residencesTab.waitForExistence(timeout: 15) else {
|
|
XCTFail("Main screen did not appear")
|
|
return
|
|
}
|
|
|
|
// App has 4 tabs: Residences, Tasks, Contractors, Documents
|
|
XCTAssertTrue(main.residencesTab.exists, "Residences tab should exist")
|
|
XCTAssertTrue(main.tasksTab.exists, "Tasks tab should exist")
|
|
XCTAssertTrue(main.contractorsTab.exists, "Contractors tab should exist")
|
|
XCTAssertTrue(main.documentsTab.exists, "Documents tab should exist")
|
|
}
|
|
|
|
func testTabNavigation() {
|
|
let login = LoginScreen(app: app)
|
|
if login.emailField.waitForExistence(timeout: 15) {
|
|
let user = TestFixtures.TestUser.existing
|
|
login.login(email: user.email, password: user.password)
|
|
}
|
|
|
|
let main = MainTabScreen(app: app)
|
|
guard main.residencesTab.waitForExistence(timeout: 15) else {
|
|
XCTFail("Main screen did not appear")
|
|
return
|
|
}
|
|
|
|
// Navigate through each tab and verify selection
|
|
main.goToTasks()
|
|
XCTAssertTrue(main.tasksTab.isSelected, "Tasks tab should be selected")
|
|
|
|
main.goToContractors()
|
|
XCTAssertTrue(main.contractorsTab.isSelected, "Contractors tab should be selected")
|
|
|
|
main.goToDocuments()
|
|
XCTAssertTrue(main.documentsTab.isSelected, "Documents tab should be selected")
|
|
|
|
main.goToResidences()
|
|
XCTAssertTrue(main.residencesTab.isSelected, "Residences tab should be selected")
|
|
}
|
|
}
|