* Fix testUserFlow integration tests - Use 'Close' instead of 'Cancel' button label when dismissing location picker - Scroll up to make the People button visible before tapping it Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fixup! Fix testUserFlow integration tests * Integration tests: Add logout handling for MAS authentication It is useful when relaunching tests locally. It avoids them to fail because the MAS webview is already logged it from a previous session. * Swipe until the People button is hittable. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Doug <douglase@element.io>
151 lines
6.9 KiB
Swift
151 lines
6.9 KiB
Swift
//
|
|
// Copyright 2025 Element Creations Ltd.
|
|
// Copyright 2023-2025 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
|
|
|
|
enum IntegrationTestsError: Error {
|
|
case webAuthenticationSessionFailure
|
|
}
|
|
|
|
extension XCUIApplication {
|
|
private var doesNotExistPredicate: NSPredicate {
|
|
NSPredicate(format: "exists == 0")
|
|
}
|
|
|
|
func login(currentTestCase: XCTestCase) throws {
|
|
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.")
|
|
throw IntegrationTestsError.webAuthenticationSessionFailure
|
|
}
|
|
|
|
if alerts.count > 0 {
|
|
alerts.firstMatch.buttons["OK"].firstMatch.tap()
|
|
}
|
|
}
|
|
|
|
webAuthenticationSessionAlertContinueButton.tap(.center)
|
|
|
|
let webAuthenticationView = XCUIApplication(bundleIdentifier: "com.apple.SafariViewService")
|
|
XCTAssertTrue(webAuthenticationView.waitForExistence(timeout: 10.0))
|
|
webAuthenticationView.tap(.top) // Tap the web view to properly focus the app again.
|
|
|
|
// The user may already be authenticated on MAS. Sign them out.
|
|
// The button label varies by MAS version: "Sign out" or "Use another account".
|
|
let webLogoutPredicate = NSPredicate(format: "label == 'Sign out' OR label == 'Use another account'")
|
|
let webLogoutButton = webAuthenticationView.buttons.matching(webLogoutPredicate).firstMatch
|
|
if webLogoutButton.waitForExistence(timeout: 2.0) {
|
|
webLogoutButton.tap(.center)
|
|
}
|
|
|
|
let webUsernameTextField = textFields["Username or Email"]
|
|
XCTAssertTrue(webUsernameTextField.waitForExistence(timeout: 10.0))
|
|
webUsernameTextField.clearAndTypeText(username, app: self)
|
|
webAuthenticationView.buttons["Done"].firstMatch.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)
|
|
webAuthenticationView.buttons["Done"].firstMatch.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 (Remove this device)
|
|
let alertLogoutButton = alerts.firstMatch.buttons[A11yIdentifiers.alertInfo.primaryButton].firstMatch
|
|
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))
|
|
}
|
|
}
|