// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import ElementX import XCTest @MainActor class LoginScreenUITests: XCTestCase { var app: XCUIApplication! @MainActor override func setUp() async throws { app = nil } func testMatrixDotOrg() { // Given the initial login screen which defaults to matrix.org. app = Application.launch() app.goToScreenWithIdentifier(.login) let state = "matrix.org" validateLoginFormIsVisible(for: state) validateOIDCButtonIsHidden(for: state) validateNextButtonIsDisabled(for: state) validateUnsupportedServerTextIsHidden(for: state) app.assertScreenshot(.login) // When typing in a username and password. app.textFields.element.tap() app.typeText("@test:matrix.org") app.secureTextFields.element.tap() app.typeText("12345678") // Then the form should be ready to submit. validateNextButtonIsEnabled(for: "matrix.org with credentials entered") } func testOIDC() { // Given the initial login screen. app = Application.launch() app.goToScreenWithIdentifier(.login) // When entering a username on a homeserver that only supports OIDC. app.textFields.element.tap() app.typeText("@test:company.com\n") // Then the screen should be configured for OIDC. let state = "an OIDC only server" validateOIDCButtonIsShown(for: state) validateLoginFormIsHidden(for: state) validateUnsupportedServerTextIsHidden(for: state) } func testUnsupported() { // Given the initial login screen. app = Application.launch() app.goToScreenWithIdentifier(.login) // When entering a username on a homeserver with an unsupported flow. app.textFields.element.tap() app.typeText("@test:server.net\n") // Then the screen should not allow login to continue. let state = "an unsupported server" validateUnsupportedServerTextIsShown(for: state) validateLoginFormIsHidden(for: state) validateOIDCButtonIsHidden(for: state) } /// Checks that the username and password text fields are shown along with the next button. func validateLoginFormIsVisible(for state: String) { let usernameTextField = app.textFields.element let passwordTextField = app.secureTextFields.element let nextButton = app.buttons["nextButton"] XCTAssertTrue(usernameTextField.exists, "Username input should be shown for \(state).") XCTAssertTrue(passwordTextField.exists, "Password input should be shown for \(state).") XCTAssertTrue(nextButton.exists, "The next button should be shown for \(state).") XCTAssertEqual(nextButton.label, ElementL10n.loginSignupSubmit) } /// Checks that the username and password text fields are hidden along with the next button. func validateLoginFormIsHidden(for state: String) { let usernameTextField = app.textFields.element let passwordTextField = app.secureTextFields.element let nextButton = app.buttons["nextButton"] XCTAssertFalse(usernameTextField.exists, "Username input should not be shown for \(state).") XCTAssertFalse(passwordTextField.exists, "Password input should not be shown for \(state).") XCTAssertFalse(nextButton.exists, "The next button should not be shown for \(state).") } /// Checks that the next button is shown but is disabled. func validateNextButtonIsDisabled(for state: String) { let nextButton = app.buttons["nextButton"] XCTAssertTrue(nextButton.exists, "The next button should be shown.") XCTAssertFalse(nextButton.isEnabled, "The next button should be disabled for \(state).") XCTAssertEqual(nextButton.label, ElementL10n.loginSignupSubmit) } /// Checks that the next button is shown and is enabled. func validateNextButtonIsEnabled(for state: String) { let nextButton = app.buttons["nextButton"] XCTAssertTrue(nextButton.exists, "The next button should be shown.") XCTAssertTrue(nextButton.isEnabled, "The next button should be enabled for \(state).") XCTAssertEqual(nextButton.label, ElementL10n.loginSignupSubmit) } /// Checks that the OIDC button is shown on the screen. func validateOIDCButtonIsShown(for state: String) { let oidcButton = app.buttons["oidcButton"] XCTAssertTrue(oidcButton.waitForExistence(timeout: 1), "The OIDC button should be shown for \(state).") XCTAssertEqual(oidcButton.label, ElementL10n.loginContinue) } /// Checks that the OIDC button is not shown on the screen. func validateOIDCButtonIsHidden(for state: String) { let oidcButton = app.buttons["oidcButton"] XCTAssertFalse(oidcButton.exists, "The OIDC button should be hidden for \(state).") } /// Checks that the unsupported homeserver text is shown on the screen. func validateUnsupportedServerTextIsShown(for state: String) { let unsupportedText = app.staticTexts["unsupportedServerText"] XCTAssertTrue(unsupportedText.waitForExistence(timeout: 1), "The unsupported homeserver text should be shown for \(state).") XCTAssertEqual(unsupportedText.label, ElementL10n.autodiscoverWellKnownError) } /// Checks that the unsupported homeserver text is not shown on the screen. func validateUnsupportedServerTextIsHidden(for state: String) { let unsupportedText = app.staticTexts["unsupportedServerText"] XCTAssertFalse(unsupportedText.exists, "The unsupported homeserver text should be hidden for \(state).") } }