// // Copyright 2023, 2024 New Vector Ltd. // // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial // Please see LICENSE files in the repository root for full details. // import XCTest extension XCUIApplication { private var doesNotExistPredicate: NSPredicate { NSPredicate(format: "exists == 0") } func login(currentTestCase: XCTestCase) { let getStartedButton = buttons[A11yIdentifiers.authenticationStartScreen.signIn] XCTAssertTrue(getStartedButton.waitForExistence(timeout: 10.0)) getStartedButton.tap(.center) if let homeserver { let changeHomeserverButton = buttons[A11yIdentifiers.serverConfirmationScreen.changeServer] XCTAssertTrue(changeHomeserverButton.waitForExistence(timeout: 10.0)) changeHomeserverButton.tap(.center) let homeserverTextField = textFields[A11yIdentifiers.changeServerScreen.server] XCTAssertTrue(homeserverTextField.waitForExistence(timeout: 10.0)) homeserverTextField.clearAndTypeText(homeserver, app: self) let confirmButton = buttons[A11yIdentifiers.changeServerScreen.continue] XCTAssertTrue(confirmButton.waitForExistence(timeout: 10.0)) confirmButton.tap(.center) // Wait for server confirmation to finish currentTestCase.expectation(for: doesNotExistPredicate, evaluatedWith: confirmButton) currentTestCase.waitForExpectations(timeout: 300.0) } let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") let webAuthenticationSessionAlertContinueButton = springboard.buttons["Continue"].firstMatch // On a fresh simulator the webcredentials association is sometimes slow to be resolved. // This results in an error alert being shown instead of the Web Authentication Session alert. // Keep looping on the Continue button for ~5 minutes until the Authentication Session is happy. var remainingAttempts = 10 while !webAuthenticationSessionAlertContinueButton.exists { let continueButton = buttons[A11yIdentifiers.serverConfirmationScreen.continue] XCTAssertTrue(continueButton.waitForExistence(timeout: 30.0)) continueButton.tap(.center) if webAuthenticationSessionAlertContinueButton.waitForExistence(timeout: 30.0) { break } remainingAttempts -= 1 if remainingAttempts <= 0 { XCTFail("Failed to present the web authentication session.") } if alerts.count > 0 { alerts.firstMatch.buttons["OK"].tap() } } webAuthenticationSessionAlertContinueButton.tap(.center) let webAuthenticationView = webViews.firstMatch XCTAssertTrue(webAuthenticationView.waitForExistence(timeout: 10.0)) webAuthenticationView.tap(.top) // Tap the web view to properly focus the app again. let webUsernameTextField = textFields["Username or Email"] XCTAssertTrue(webUsernameTextField.waitForExistence(timeout: 10.0)) webUsernameTextField.clearAndTypeText(username, app: self) buttons["Done"].tap() // Dismiss the keyboard so that the password text field is fully hittable. let webPasswordTextField = secureTextFields["Password"] XCTAssertTrue(webPasswordTextField.waitForExistence(timeout: 10.0)) webPasswordTextField.clearAndTypeText(password, app: self) buttons["Done"].tap() // Dismiss the keyboard so that the continue button is fully hittable. let webLoginButton = webAuthenticationView.buttons["Continue"] XCTAssertTrue(webLoginButton.waitForExistence(timeout: 10.0)) webLoginButton.tap(.center) // Handle the password saving dialog let savePasswordButton = buttons["Save Password"] if savePasswordButton.waitForExistence(timeout: 10.0) { // Tapping the sheet button while animating upwards fails. Wait for it to settle sleep(1) buttons["Not Now"].tap(.center) } let webConsentButton = webAuthenticationView.buttons["Continue"] XCTAssertTrue(webConsentButton.waitForExistence(timeout: 10.0)) webConsentButton.tap(.center) // Wait for login to finish currentTestCase.expectation(for: doesNotExistPredicate, evaluatedWith: webUsernameTextField) currentTestCase.waitForExpectations(timeout: 300.0) // Wait for the home screen to become visible. let profileButton = buttons[A11yIdentifiers.homeScreen.userAvatar] // Timeouts are huge because we're waiting for the server. XCTAssertTrue(profileButton.waitForExistence(timeout: 300.0)) } func logout() { // On first login when multiple sheets get presented the profile button is not hittable // Moving the scroll fixed it for some obscure reason swipeDown() let profileButton = buttons[A11yIdentifiers.homeScreen.userAvatar] // `Failed to scroll to visible (by AX action) Button` https://stackoverflow.com/a/33534187/730924 profileButton.tap(.center) // Make the logout button visible swipeUp() // Logout let logoutButton = buttons[A11yIdentifiers.settingsScreen.logout] XCTAssertTrue(logoutButton.waitForExistence(timeout: 10.0)) logoutButton.tap(.center) // Confirm logout let alertLogoutButton = alerts.firstMatch.buttons["Sign out"] XCTAssertTrue(alertLogoutButton.waitForExistence(timeout: 10.0)) alertLogoutButton.tap(.center) // Check that we're back on the login screen let getStartedButton = buttons[A11yIdentifiers.authenticationStartScreen.signIn] XCTAssertTrue(getStartedButton.waitForExistence(timeout: 10.0)) } }