Ask the iPad to reveal the keyboard in UI Tests when it's hidden. (#3389)

This commit is contained in:
Doug
2024-10-10 08:38:40 +01:00
committed by GitHub
parent fbccf7ff06
commit 2e9df064ca
7 changed files with 34 additions and 16 deletions

View File

@@ -8,9 +8,11 @@
import XCTest import XCTest
extension XCUIElement { extension XCUIElement {
func clearAndTypeText(_ text: String) { func clearAndTypeText(_ text: String, app: XCUIApplication) {
tapCenter() tapCenter()
app.showKeyboardIfNeeded()
guard let currentValue = value as? String else { guard let currentValue = value as? String else {
XCTFail("Tried to clear and type text into a non string value") XCTFail("Tried to clear and type text into a non string value")
return return
@@ -29,3 +31,17 @@ extension XCUIElement {
coordinate.tap() coordinate.tap()
} }
} }
extension XCUIApplication {
/// Ensures the software keyboard is shown on an iPad when a text field is focussed.
///
/// Note: Whilst this could be added on XCUIElement to more closely tie it to a text field, it requires the
/// app instance anyway, and some of our tests assert that a default focus has been set on the text field,
/// so having a method that would set the focus and show the keyboard isn't always desirable.
func showKeyboardIfNeeded() {
if UIDevice.current.userInterfaceIdiom == .pad, keyboards.count == 0 {
buttons["Keyboard"].tap()
buttons["Show Keyboard"].tap()
}
}
}

View File

@@ -119,6 +119,8 @@ class AppLockSetupUITests: XCTestCase {
func testCancel() async throws { func testCancel() async throws {
app = Application.launch(.appLockSetupFlowUnlock) app = Application.launch(.appLockSetupFlowUnlock)
app.showKeyboardIfNeeded() // The secure text field is focussed automatically
// Create PIN screen. // Create PIN screen.
try await app.assertScreenshot(.appLockSetupFlowUnlock) try await app.assertScreenshot(.appLockSetupFlowUnlock)
@@ -134,13 +136,13 @@ class AppLockSetupUITests: XCTestCase {
let textField = app.secureTextFields[A11yIdentifiers.appLockSetupPINScreen.textField] let textField = app.secureTextFields[A11yIdentifiers.appLockSetupPINScreen.textField]
XCTAssert(textField.waitForExistence(timeout: 10)) XCTAssert(textField.waitForExistence(timeout: 10))
textField.clearAndTypeText("2023") textField.clearAndTypeText("2023", app: app)
} }
private func enterDifferentPIN() { private func enterDifferentPIN() {
let textField = app.secureTextFields[A11yIdentifiers.appLockSetupPINScreen.textField] let textField = app.secureTextFields[A11yIdentifiers.appLockSetupPINScreen.textField]
XCTAssert(textField.waitForExistence(timeout: 10)) XCTAssert(textField.waitForExistence(timeout: 10))
textField.clearAndTypeText("2233") textField.clearAndTypeText("2233", app: app)
} }
} }

View File

@@ -24,8 +24,8 @@ class AuthenticationFlowCoordinatorUITests: XCTestCase {
XCTAssertTrue(continueButton.waitForExistence(timeout: 2.0)) XCTAssertTrue(continueButton.waitForExistence(timeout: 2.0))
// Login Screen: Enter valid credentials // Login Screen: Enter valid credentials
app.textFields[A11yIdentifiers.loginScreen.emailUsername].clearAndTypeText("alice\n") app.textFields[A11yIdentifiers.loginScreen.emailUsername].clearAndTypeText("alice\n", app: app)
app.secureTextFields[A11yIdentifiers.loginScreen.password].clearAndTypeText("12345678") app.secureTextFields[A11yIdentifiers.loginScreen.password].clearAndTypeText("12345678", app: app)
try await app.assertScreenshot(.authenticationFlow) try await app.assertScreenshot(.authenticationFlow)
@@ -48,8 +48,8 @@ class AuthenticationFlowCoordinatorUITests: XCTestCase {
XCTAssertTrue(continueButton.waitForExistence(timeout: 2.0)) XCTAssertTrue(continueButton.waitForExistence(timeout: 2.0))
// Login Screen: Enter invalid credentials // Login Screen: Enter invalid credentials
app.textFields[A11yIdentifiers.loginScreen.emailUsername].clearAndTypeText("alice") app.textFields[A11yIdentifiers.loginScreen.emailUsername].clearAndTypeText("alice", app: app)
app.secureTextFields[A11yIdentifiers.loginScreen.password].clearAndTypeText("87654321") app.secureTextFields[A11yIdentifiers.loginScreen.password].clearAndTypeText("87654321", app: app)
// Login Screen: Tap continue // Login Screen: Tap continue
XCTAssertTrue(continueButton.isEnabled) XCTAssertTrue(continueButton.isEnabled)
@@ -74,7 +74,7 @@ class AuthenticationFlowCoordinatorUITests: XCTestCase {
XCTAssertTrue(continueButton.waitForExistence(timeout: 2.0)) XCTAssertTrue(continueButton.waitForExistence(timeout: 2.0))
// When entering a username on a homeserver with an unsupported flow. // When entering a username on a homeserver with an unsupported flow.
app.textFields[A11yIdentifiers.loginScreen.emailUsername].clearAndTypeText("@test:server.net\n") app.textFields[A11yIdentifiers.loginScreen.emailUsername].clearAndTypeText("@test:server.net\n", app: app)
// Then the screen should not allow login to continue. // Then the screen should not allow login to continue.
try await app.assertScreenshot(.authenticationFlow, step: 1) try await app.assertScreenshot(.authenticationFlow, step: 1)
@@ -91,7 +91,7 @@ class AuthenticationFlowCoordinatorUITests: XCTestCase {
app.buttons[A11yIdentifiers.serverConfirmationScreen.changeServer].tap() app.buttons[A11yIdentifiers.serverConfirmationScreen.changeServer].tap()
// Server Selection: Clear the default, enter OIDC server and continue. // Server Selection: Clear the default, enter OIDC server and continue.
app.textFields[A11yIdentifiers.changeServerScreen.server].clearAndTypeText("company.com\n") app.textFields[A11yIdentifiers.changeServerScreen.server].clearAndTypeText("company.com\n", app: app)
// Server Confirmation: Tap continue button // Server Confirmation: Tap continue button
app.buttons[A11yIdentifiers.serverConfirmationScreen.continue].tap() app.buttons[A11yIdentifiers.serverConfirmationScreen.continue].tap()

View File

@@ -20,13 +20,13 @@ class BugReportUITests: XCTestCase {
let app = Application.launch(.bugReport) let app = Application.launch(.bugReport)
// Type 4 characters and the send button should be disabled. // Type 4 characters and the send button should be disabled.
app.textViews[A11yIdentifiers.bugReportScreen.report].clearAndTypeText("Text") app.textViews[A11yIdentifiers.bugReportScreen.report].clearAndTypeText("Text", app: app)
XCTAssert(app.switches[A11yIdentifiers.bugReportScreen.sendLogs].isOn) XCTAssert(app.switches[A11yIdentifiers.bugReportScreen.sendLogs].isOn)
XCTAssert(!app.switches[A11yIdentifiers.bugReportScreen.canContact].isOn) XCTAssert(!app.switches[A11yIdentifiers.bugReportScreen.canContact].isOn)
try await app.assertScreenshot(.bugReport, step: 2) try await app.assertScreenshot(.bugReport, step: 2)
// Type more than 4 characters and send the button should become enabled. // Type more than 4 characters and send the button should become enabled.
app.textViews[A11yIdentifiers.bugReportScreen.report].clearAndTypeText("Longer text") app.textViews[A11yIdentifiers.bugReportScreen.report].clearAndTypeText("Longer text", app: app)
XCTAssert(app.switches[A11yIdentifiers.bugReportScreen.sendLogs].isOn) XCTAssert(app.switches[A11yIdentifiers.bugReportScreen.sendLogs].isOn)
XCTAssert(!app.switches[A11yIdentifiers.bugReportScreen.canContact].isOn) XCTAssert(!app.switches[A11yIdentifiers.bugReportScreen.canContact].isOn)
try await app.assertScreenshot(.bugReport, step: 3) try await app.assertScreenshot(.bugReport, step: 3)

View File

@@ -19,7 +19,7 @@ class RoomMembersListScreenUITests: XCTestCase {
let app = Application.launch(.roomMembersListScreenPendingInvites) let app = Application.launch(.roomMembersListScreenPendingInvites)
let searchBar = app.searchFields.firstMatch let searchBar = app.searchFields.firstMatch
searchBar.clearAndTypeText("alice\n") searchBar.clearAndTypeText("alice\n", app: app)
try await app.assertScreenshot(.roomMembersListScreenPendingInvites, step: 1) try await app.assertScreenshot(.roomMembersListScreenPendingInvites, step: 1)
} }
@@ -28,7 +28,7 @@ class RoomMembersListScreenUITests: XCTestCase {
let app = Application.launch(.roomMembersListScreenPendingInvites) let app = Application.launch(.roomMembersListScreenPendingInvites)
let searchBar = app.searchFields.firstMatch let searchBar = app.searchFields.firstMatch
searchBar.clearAndTypeText("bob\n") searchBar.clearAndTypeText("bob\n", app: app)
try await app.assertScreenshot(.roomMembersListScreenPendingInvites, step: 2) try await app.assertScreenshot(.roomMembersListScreenPendingInvites, step: 2)
} }

View File

@@ -34,7 +34,7 @@ class ServerSelectionUITests: XCTestCase {
let app = Application.launch(.serverSelection) let app = Application.launch(.serverSelection)
// When typing in an invalid homeserver // When typing in an invalid homeserver
app.textFields[A11yIdentifiers.changeServerScreen.server].clearAndTypeText("thisisbad\n") // The tests only accept an address from LoginHomeserver.mockXYZ app.textFields[A11yIdentifiers.changeServerScreen.server].clearAndTypeText("thisisbad\n", app: app) // The tests only accept an address from LoginHomeserver.mockXYZ
// Then an error should be shown and the confirmation button disabled. // Then an error should be shown and the confirmation button disabled.
try await app.assertScreenshot(.serverSelection, step: 2) try await app.assertScreenshot(.serverSelection, step: 2)

View File

@@ -17,7 +17,7 @@ class StartChatScreenUITests: XCTestCase {
func testSearchWithNoResults() async throws { func testSearchWithNoResults() async throws {
let app = Application.launch(.startChat) let app = Application.launch(.startChat)
let searchField = app.searchFields.firstMatch let searchField = app.searchFields.firstMatch
searchField.clearAndTypeText("None\n") searchField.clearAndTypeText("None\n", app: app)
XCTAssert(app.staticTexts[A11yIdentifiers.startChatScreen.searchNoResults].waitForExistence(timeout: 1.0)) XCTAssert(app.staticTexts[A11yIdentifiers.startChatScreen.searchNoResults].waitForExistence(timeout: 1.0))
try await app.assertScreenshot(.startChat, step: 1) try await app.assertScreenshot(.startChat, step: 1)
} }
@@ -25,7 +25,7 @@ class StartChatScreenUITests: XCTestCase {
func testSearchWithResults() async throws { func testSearchWithResults() async throws {
let app = Application.launch(.startChatWithSearchResults) let app = Application.launch(.startChatWithSearchResults)
let searchField = app.searchFields.firstMatch let searchField = app.searchFields.firstMatch
searchField.clearAndTypeText("Bob\n") searchField.clearAndTypeText("Bob\n", app: app)
XCTAssertFalse(app.staticTexts[A11yIdentifiers.startChatScreen.searchNoResults].waitForExistence(timeout: 1.0)) XCTAssertFalse(app.staticTexts[A11yIdentifiers.startChatScreen.searchNoResults].waitForExistence(timeout: 1.0))
XCTAssertEqual(app.collectionViews.firstMatch.cells.count, 2) XCTAssertEqual(app.collectionViews.firstMatch.cells.count, 2)
try await app.assertScreenshot(.startChat, step: 2) try await app.assertScreenshot(.startChat, step: 2)