import XCTest /// Comprehensive tests for authentication flows final class AuthenticationUITests: BaseUITest { // MARK: - Login Tests func testLoginWithValidCredentials() { // Given: User is on login screen XCTAssertTrue(app.staticTexts["MyCrib"].exists) // When: User enters valid credentials and taps login login(username: "testuser", password: "TestPass123!") // Then: User should be navigated to main screen let residencesTab = app.tabBars.buttons["Residences"] XCTAssertTrue(residencesTab.waitForExistence(timeout: 10), "Should navigate to main tab view") } func testLoginWithInvalidCredentials() { // Given: User is on login screen XCTAssertTrue(app.staticTexts["MyCrib"].exists) // When: User enters invalid credentials login(username: "invaliduser", password: "WrongPassword!") // Then: Error message should be displayed let errorMessage = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'Invalid username or password'")) XCTAssertTrue(errorMessage.firstMatch.waitForExistence(timeout: 5), "Should show error message") // And: User should remain on login screen XCTAssertTrue(app.staticTexts["MyCrib"].exists) } func testLoginWithEmptyFields() { // Given: User is on login screen let loginButton = app.buttons["Login"] // When: User taps login without entering credentials loginButton.tap() // Then: Validation error should be shown let usernameError = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'Username is required'")) XCTAssertTrue(usernameError.firstMatch.waitForExistence(timeout: 3), "Should show username required error") } func testPasswordVisibilityToggle() { // Given: User has typed password let passwordField = app.secureTextFields["Password"] let textField = app.textFields["Password"] let toggleButton = app.buttons.matching(identifier: "eye").firstMatch passwordField.tap() passwordField.typeText("TestPassword") // When: User taps the visibility toggle toggleButton.tap() // Then: Password should be visible as text XCTAssertTrue(textField.exists, "Password should be visible") // When: User taps toggle again toggleButton.tap() // Then: Password should be hidden again XCTAssertTrue(passwordField.exists, "Password should be secure") } // MARK: - Registration Tests func testRegistrationWithValidData() { // Given: User is on login screen let signUpButton = app.buttons["Sign Up"] // When: User taps Sign Up signUpButton.tap() // Then: Registration screen should be displayed assertNavigatedTo(title: "Create Account", timeout: 3) // When: User fills in valid registration data let timestamp = Int(Date().timeIntervalSince1970) register( username: "newuser\(timestamp)", email: "newuser\(timestamp)@test.com", password: "TestPass123!", firstName: "Test", lastName: "User" ) // Then: User should be registered and shown verification screen let verificationTitle = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'Verify'")) XCTAssertTrue(verificationTitle.firstMatch.waitForExistence(timeout: 10), "Should show verification screen") } func testRegistrationWithExistingUsername() { // Given: User is on registration screen let signUpButton = app.buttons["Sign Up"] signUpButton.tap() // When: User registers with existing username register( username: "existinguser", email: "newemail@test.com", password: "TestPass123!" ) // Then: Error message should be displayed let errorMessage = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'username' OR label CONTAINS[c] 'already exists'")) XCTAssertTrue(errorMessage.firstMatch.waitForExistence(timeout: 5), "Should show username exists error") } func testRegistrationWithInvalidEmail() { // Given: User is on registration screen let signUpButton = app.buttons["Sign Up"] signUpButton.tap() // When: User enters invalid email let emailField = app.textFields["Email"] let registerButton = app.buttons["Register"] emailField.tap() emailField.typeText("invalidemail") registerButton.tap() // Then: Email validation error should be shown let errorMessage = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'valid email'")) XCTAssertTrue(errorMessage.firstMatch.waitForExistence(timeout: 3), "Should show email validation error") } func testRegistrationWithWeakPassword() { // Given: User is on registration screen let signUpButton = app.buttons["Sign Up"] signUpButton.tap() // When: User enters weak password let timestamp = Int(Date().timeIntervalSince1970) let usernameField = app.textFields["Username"] let emailField = app.textFields["Email"] let passwordField = app.secureTextFields["Password"] let registerButton = app.buttons["Register"] usernameField.tap() usernameField.typeText("testuser\(timestamp)") emailField.tap() emailField.typeText("test\(timestamp)@test.com") passwordField.tap() passwordField.typeText("weak") registerButton.tap() // Then: Password validation error should be shown let errorMessage = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'password' AND (label CONTAINS[c] 'strong' OR label CONTAINS[c] 'at least')")) XCTAssertTrue(errorMessage.firstMatch.waitForExistence(timeout: 3), "Should show password strength error") } // MARK: - Logout Tests func testLogoutFlow() { // Given: User is logged in login(username: "testuser", password: "TestPass123!") let residencesTab = app.tabBars.buttons["Residences"] XCTAssertTrue(residencesTab.waitForExistence(timeout: 10)) // When: User logs out logout() // Then: User should be returned to login screen XCTAssertTrue(app.staticTexts["MyCrib"].waitForExistence(timeout: 5), "Should return to login screen") XCTAssertTrue(app.buttons["Login"].exists, "Login button should be visible") } func testLogoutClearsUserData() { // Given: User is logged in and has viewed some data login(username: "testuser", password: "TestPass123!") let residencesTab = app.tabBars.buttons["Residences"] XCTAssertTrue(residencesTab.waitForExistence(timeout: 10)) navigateToTab("Residences") wait(seconds: 2) // Wait for data to load // When: User logs out logout() // And: User logs back in login(username: "testuser", password: "TestPass123!") // Then: Fresh data should be loaded (not cached) let loadingIndicator = app.activityIndicators.firstMatch XCTAssertTrue(loadingIndicator.exists || app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'Loading'")).firstMatch.exists, "Should show loading state for fresh data") } // MARK: - Session Management Tests func testSessionPersistence() { // Given: User logs in login(username: "testuser", password: "TestPass123!") let residencesTab = app.tabBars.buttons["Residences"] XCTAssertTrue(residencesTab.waitForExistence(timeout: 10)) // When: App is terminated and relaunched app.terminate() app.launch() // Then: User should still be logged in XCTAssertTrue(residencesTab.waitForExistence(timeout: 5), "User session should persist") } func testLoginRedirectsVerifiedUser() { // Given: Verified user logs in login(username: "verifieduser", password: "TestPass123!") // Then: User should go directly to main screen (not verification) let residencesTab = app.tabBars.buttons["Residences"] XCTAssertTrue(residencesTab.waitForExistence(timeout: 10), "Verified user should skip verification") } func testLoginRedirectsUnverifiedUser() { // Given: Unverified user logs in login(username: "unverifieduser", password: "TestPass123!") // Then: User should be shown verification screen let verificationTitle = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'Verify'")) XCTAssertTrue(verificationTitle.firstMatch.waitForExistence(timeout: 10), "Unverified user should see verification screen") } // MARK: - Error Handling Tests func testLoginWithNetworkError() { // Note: This test requires network simulation or mocking // For now, it's a placeholder for future implementation // Given: Network is unavailable // When: User attempts to login // Then: Network error should be displayed } func testLoginRetryAfterError() { // Given: User encountered a login error login(username: "invaliduser", password: "WrongPassword!") let errorMessage = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'Invalid'")) XCTAssertTrue(errorMessage.firstMatch.waitForExistence(timeout: 5)) // When: User enters correct credentials let usernameField = app.textFields["Username"] let passwordField = app.secureTextFields["Password"] let loginButton = app.buttons["Login"] app.clearText(in: usernameField) usernameField.typeText("testuser") app.clearText(in: passwordField) passwordField.typeText("TestPass123!") loginButton.tap() // Then: Login should succeed let residencesTab = app.tabBars.buttons["Residences"] XCTAssertTrue(residencesTab.waitForExistence(timeout: 10), "Should login successfully after retry") } }