mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-10-31 16:24:11 +00:00
8ead25eaa3
Tapping the SafariViewService app object makes XCUITest activate it as a standalone app. That backgrounds Element X, which hosts the web view, so the hosted scene goes to the background too and WebKit suspends it mid load. The sign in page is fetched successfully but never rendered, and the test times out waiting for the username field. The tap dates from when the element was a web view inside the app, where it was a plain in app tap, so it no longer does what its comment describes.
138 lines
6.2 KiB
Swift
138 lines
6.2 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 {
|
|
// Server selection screen appears directly after sign in
|
|
let homeserverTextField = textFields[A11yIdentifiers.changeServerScreen.server]
|
|
XCTAssertTrue(homeserverTextField.waitForExistence(timeout: 10.0))
|
|
homeserverTextField.clearAndTypeText(homeserver, app: self)
|
|
}
|
|
|
|
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.changeServerScreen.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.firstMatch.exists {
|
|
alerts.firstMatch.buttons["OK"].firstMatch.tap()
|
|
}
|
|
}
|
|
|
|
webAuthenticationSessionAlertContinueButton.tap(.center)
|
|
|
|
let webAuthenticationView = XCUIApplication(bundleIdentifier: "com.apple.SafariViewService")
|
|
XCTAssertTrue(webAuthenticationView.waitForExistence(timeout: 10.0))
|
|
|
|
// 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))
|
|
}
|
|
}
|