mirror of
https://github.com/element-hq/element-x-ios.git
synced 2025-03-10 13:37:11 +00:00
Disable broken UI Tests and remove navigation. (#577)
Add locale to signalling service name. Type strings character by character. Add a default test timeout of 1 minute. * Directly set UI Tests screens as the root screen. Speeds up test runs by removing scrolling and searching for buttons. * Parallelise test runs from Xcode (not fastlane). * Disable signalling based tests.
This commit is contained in:
parent
944660800a
commit
21154c7eef
@ -18,45 +18,18 @@ import XCTest
|
||||
|
||||
extension XCUIElement {
|
||||
func clearAndTypeText(_ text: String) {
|
||||
let maxAttemptCount = 10
|
||||
var attemptCount = 0
|
||||
tap()
|
||||
|
||||
repeat {
|
||||
tap()
|
||||
|
||||
guard let currentValue = value as? String else {
|
||||
XCTFail("Tried to clear and type text into a non string value")
|
||||
return
|
||||
}
|
||||
|
||||
let deleteString = String(repeating: XCUIKeyboardKey.delete.rawValue, count: currentValue.count)
|
||||
|
||||
typeText(deleteString)
|
||||
typeText(text)
|
||||
|
||||
if !exists { // Break if the element in question doesn't exist anymore
|
||||
break
|
||||
}
|
||||
|
||||
guard let newValue = value as? String else {
|
||||
XCTFail("Tried to clear and type text into a non string value")
|
||||
return
|
||||
}
|
||||
|
||||
if newValue == String(repeating: "•", count: text.count) { // Secure entry text field
|
||||
break
|
||||
}
|
||||
|
||||
if newValue == text.trimmingCharacters(in: .whitespacesAndNewlines) {
|
||||
break
|
||||
}
|
||||
|
||||
attemptCount += 1
|
||||
if attemptCount > maxAttemptCount {
|
||||
XCTFail("Failed clearAndTypeText after \(maxAttemptCount) attempts.")
|
||||
return
|
||||
}
|
||||
|
||||
} while true
|
||||
guard let currentValue = value as? String else {
|
||||
XCTFail("Tried to clear and type text into a non string value")
|
||||
return
|
||||
}
|
||||
|
||||
let deleteString = String(repeating: XCUIKeyboardKey.delete.rawValue, count: currentValue.count)
|
||||
typeText(deleteString)
|
||||
|
||||
for character in text {
|
||||
typeText(String(character))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,4 +34,13 @@ public enum Tests {
|
||||
false
|
||||
#endif
|
||||
}
|
||||
|
||||
/// The identifier of the screen to be loaded when running UI tests.
|
||||
static var screenID: UITestsScreenIdentifier? {
|
||||
#if DEBUG
|
||||
ProcessInfo.processInfo.environment["UI_TESTS_SCREEN"].flatMap(UITestsScreenIdentifier.init)
|
||||
#else
|
||||
nil
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -19,13 +19,12 @@ import UIKit
|
||||
|
||||
class UITestsAppCoordinator: AppCoordinatorProtocol {
|
||||
private let navigationRootCoordinator: NavigationRootCoordinator
|
||||
private var mockScreens: [MockScreen] = []
|
||||
private var mockScreen: MockScreen?
|
||||
var notificationManager: NotificationManagerProtocol?
|
||||
|
||||
init() {
|
||||
UIView.setAnimationsEnabled(false)
|
||||
navigationRootCoordinator = NavigationRootCoordinator()
|
||||
mockScreens = UITestScreenIdentifier.allCases.map { MockScreen(id: $0, navigationRootCoordinator: navigationRootCoordinator) }
|
||||
|
||||
ServiceLocator.shared.register(userIndicatorController: MockUserIndicatorController())
|
||||
|
||||
@ -35,15 +34,11 @@ class UITestsAppCoordinator: AppCoordinatorProtocol {
|
||||
}
|
||||
|
||||
func start() {
|
||||
let rootCoordinator = UITestsRootCoordinator(mockScreens: mockScreens) { id in
|
||||
guard let screen = self.mockScreens.first(where: { $0.id == id }) else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
self.navigationRootCoordinator.setRootCoordinator(screen.coordinator)
|
||||
}
|
||||
guard let screenID = Tests.screenID else { fatalError("Unable to launch with unknown screen.") }
|
||||
|
||||
navigationRootCoordinator.setRootCoordinator(rootCoordinator)
|
||||
let mockScreen = MockScreen(id: screenID)
|
||||
navigationRootCoordinator.setRootCoordinator(mockScreen.coordinator)
|
||||
self.mockScreen = mockScreen
|
||||
|
||||
Bundle.elementFallbackLanguage = "en"
|
||||
}
|
||||
@ -55,14 +50,12 @@ class UITestsAppCoordinator: AppCoordinatorProtocol {
|
||||
|
||||
@MainActor
|
||||
class MockScreen: Identifiable {
|
||||
let id: UITestScreenIdentifier
|
||||
let id: UITestsScreenIdentifier
|
||||
|
||||
private let navigationRootCoordinator: NavigationRootCoordinator
|
||||
private var retainedState = [Any]()
|
||||
|
||||
init(id: UITestScreenIdentifier, navigationRootCoordinator: NavigationRootCoordinator) {
|
||||
init(id: UITestsScreenIdentifier) {
|
||||
self.id = id
|
||||
self.navigationRootCoordinator = navigationRootCoordinator
|
||||
}
|
||||
|
||||
lazy var coordinator: CoordinatorProtocol = {
|
||||
|
@ -1,42 +0,0 @@
|
||||
//
|
||||
// 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 SwiftUI
|
||||
|
||||
class UITestsRootCoordinator: CoordinatorProtocol {
|
||||
let mockScreens: [MockScreen]
|
||||
var selectionCallback: ((UITestScreenIdentifier) -> Void)?
|
||||
|
||||
init(mockScreens: [MockScreen], selectionCallback: ((UITestScreenIdentifier) -> Void)? = nil) {
|
||||
self.mockScreens = mockScreens
|
||||
self.selectionCallback = selectionCallback
|
||||
}
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
AnyView(body)
|
||||
}
|
||||
|
||||
private var body: some View {
|
||||
List(mockScreens) { coordinator in
|
||||
Button(coordinator.id.description) { [weak self] in
|
||||
self?.selectionCallback?(coordinator.id)
|
||||
}
|
||||
.accessibilityIdentifier(coordinator.id.rawValue)
|
||||
}
|
||||
.padding(.top, 50) // Add some top padding so the iPad split screen button isn't tapped by mistake
|
||||
.listStyle(.plain)
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
enum UITestScreenIdentifier: String {
|
||||
enum UITestsScreenIdentifier: String {
|
||||
case login
|
||||
case serverSelection
|
||||
case serverSelectionNonModal
|
||||
@ -45,14 +45,12 @@ enum UITestScreenIdentifier: String {
|
||||
case roomMemberDetailsScreen
|
||||
}
|
||||
|
||||
extension UITestScreenIdentifier: CustomStringConvertible {
|
||||
extension UITestsScreenIdentifier: CustomStringConvertible {
|
||||
var description: String {
|
||||
rawValue.titlecased()
|
||||
}
|
||||
}
|
||||
|
||||
extension UITestScreenIdentifier: CaseIterable { }
|
||||
|
||||
private extension String {
|
||||
func titlecased() -> String {
|
||||
replacingOccurrences(of: "([A-Z])",
|
@ -50,7 +50,7 @@ enum UITestsSignalError: Error {
|
||||
enum UITestsSignalling {
|
||||
/// The Bonjour service name used for the connection. The device name
|
||||
/// is included to allow UI tests to run on multiple devices simultaneously.
|
||||
private static let serviceName = "UITestsSignalling \(UIDevice.current.name)"
|
||||
private static let serviceName = "UITestsSignalling \(UIDevice.current.name) (\(Locale.current.identifier))"
|
||||
/// The Bonjour service type used for the connection.
|
||||
private static let serviceType = "_signalling._udp."
|
||||
/// The Bonjour domain used for the connection.
|
||||
|
@ -19,8 +19,7 @@ import XCTest
|
||||
|
||||
class TemplateScreenUITests: XCTestCase {
|
||||
func testRegularScreen() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.simpleRegular)
|
||||
let app = Application.launch(.simpleRegular)
|
||||
|
||||
let title = app.staticTexts["title"]
|
||||
XCTAssert(title.exists)
|
||||
@ -31,8 +30,7 @@ class TemplateScreenUITests: XCTestCase {
|
||||
}
|
||||
|
||||
func testUpgradeScreen() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.simpleUpgrade)
|
||||
let app = Application.launch(.simpleUpgrade)
|
||||
|
||||
let title = app.staticTexts["title"]
|
||||
XCTAssert(title.exists)
|
||||
|
@ -20,8 +20,7 @@ import XCTest
|
||||
class AnalyticsPromptUITests: XCTestCase {
|
||||
/// Verify that the prompt is displayed correctly.
|
||||
func testAnalyticsPrompt() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.analyticsPrompt)
|
||||
let app = Application.launch(.analyticsPrompt)
|
||||
app.assertScreenshot(.analyticsPrompt)
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,12 @@ import SnapshotTesting
|
||||
import XCTest
|
||||
|
||||
struct Application {
|
||||
static func launch() -> XCUIApplication {
|
||||
static func launch(_ identifier: UITestsScreenIdentifier) -> XCUIApplication {
|
||||
let app = XCUIApplication()
|
||||
app.launchEnvironment = ["IS_RUNNING_UI_TESTS": "1"]
|
||||
app.launchEnvironment = [
|
||||
"IS_RUNNING_UI_TESTS": "1",
|
||||
"UI_TESTS_SCREEN": identifier.rawValue
|
||||
]
|
||||
Bundle.elementFallbackLanguage = "en"
|
||||
app.launch()
|
||||
return app
|
||||
@ -28,22 +31,11 @@ struct Application {
|
||||
}
|
||||
|
||||
extension XCUIApplication {
|
||||
func goToScreenWithIdentifier(_ identifier: UITestScreenIdentifier) {
|
||||
let button = buttons[identifier.rawValue]
|
||||
let lastLabel = staticTexts["lastItem"]
|
||||
|
||||
while !button.isHittable, !lastLabel.isHittable {
|
||||
swipeUp()
|
||||
}
|
||||
|
||||
button.tap()
|
||||
}
|
||||
|
||||
/// Assert screenshot for a screen with the given identifier. Does not fail if a screenshot is newly created.
|
||||
/// - Parameter identifier: Identifier of the UI test screen
|
||||
/// - Parameter step: An optional integer that can be used to take multiple snapshots per test identifier.
|
||||
/// - Parameter insets: Optional insets with which to crop the image by.
|
||||
func assertScreenshot(_ identifier: UITestScreenIdentifier, step: Int? = nil, insets: UIEdgeInsets? = nil) {
|
||||
func assertScreenshot(_ identifier: UITestsScreenIdentifier, step: Int? = nil, insets: UIEdgeInsets? = nil) {
|
||||
var snapshotName = identifier.rawValue
|
||||
if let step {
|
||||
snapshotName += "-\(step)"
|
||||
@ -72,7 +64,15 @@ extension XCUIApplication {
|
||||
}
|
||||
|
||||
private var deviceName: String {
|
||||
UIDevice.current.name
|
||||
var name = UIDevice.current.name
|
||||
|
||||
// When running with parallel execution simulators are named "Clone 2 of iPhone 14" etc.
|
||||
// Tidy this prefix out of the name to generate snapshots with the correct name.
|
||||
if name.starts(with: "Clone "), let range = name.range(of: " of ") {
|
||||
name = String(name[range.upperBound...])
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
private var languageCode: String {
|
||||
|
@ -22,8 +22,7 @@ import XCTest
|
||||
class AuthenticationCoordinatorUITests: XCTestCase {
|
||||
func testLoginWithPassword() {
|
||||
// Given the authentication flow.
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.authenticationFlow)
|
||||
let app = Application.launch(.authenticationFlow)
|
||||
|
||||
// Splash Screen: Tap get started button
|
||||
app.buttons["getStartedButton"].tap()
|
||||
@ -44,8 +43,7 @@ class AuthenticationCoordinatorUITests: XCTestCase {
|
||||
|
||||
func testLoginWithIncorrectPassword() async throws {
|
||||
// Given the authentication flow.
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.authenticationFlow)
|
||||
let app = Application.launch(.authenticationFlow)
|
||||
|
||||
// Splash Screen: Tap get started button
|
||||
app.buttons["getStartedButton"].tap()
|
||||
@ -66,8 +64,7 @@ class AuthenticationCoordinatorUITests: XCTestCase {
|
||||
|
||||
func testSelectingOIDCServer() {
|
||||
// Given the authentication flow.
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.authenticationFlow)
|
||||
let app = Application.launch(.authenticationFlow)
|
||||
|
||||
// Splash Screen: Tap get started button
|
||||
app.buttons["getStartedButton"].tap()
|
||||
|
@ -19,16 +19,14 @@ import XCTest
|
||||
|
||||
class BugReportUITests: XCTestCase {
|
||||
func testInitialStateComponents() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.bugReport)
|
||||
let app = Application.launch(.bugReport)
|
||||
|
||||
// Initial state without a screenshot attached.
|
||||
app.assertScreenshot(.bugReport, step: 0)
|
||||
}
|
||||
|
||||
func testToggleSendingLogs() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.bugReport)
|
||||
let app = Application.launch(.bugReport)
|
||||
|
||||
app.switches["sendLogsToggle"].tap()
|
||||
|
||||
@ -40,8 +38,7 @@ class BugReportUITests: XCTestCase {
|
||||
}
|
||||
|
||||
func testReportText() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.bugReport)
|
||||
let app = Application.launch(.bugReport)
|
||||
|
||||
// Type 4 characters and the send button should be disabled.
|
||||
app.textViews["reportTextView"].clearAndTypeText("Text")
|
||||
@ -55,8 +52,7 @@ class BugReportUITests: XCTestCase {
|
||||
}
|
||||
|
||||
func testInitialStateComponentsWithScreenshot() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.bugReportWithScreenshot)
|
||||
let app = Application.launch(.bugReportWithScreenshot)
|
||||
|
||||
// Initial state with a screenshot attached.
|
||||
XCTAssert(app.images["screenshotImage"].exists)
|
||||
|
@ -18,8 +18,7 @@ import XCTest
|
||||
|
||||
class HomeScreenUITests: XCTestCase {
|
||||
func testInitialStateComponents() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.home)
|
||||
let app = Application.launch(.home)
|
||||
|
||||
XCTAssert(app.navigationBars[ElementL10n.allChats].exists)
|
||||
|
||||
|
@ -21,8 +21,7 @@ import XCTest
|
||||
class LoginScreenUITests: XCTestCase {
|
||||
func testMatrixDotOrg() {
|
||||
// Given the initial login screen which defaults to matrix.org.
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.login)
|
||||
let app = Application.launch(.login)
|
||||
app.assertScreenshot(.login)
|
||||
|
||||
// When typing in a username and password.
|
||||
@ -35,8 +34,7 @@ class LoginScreenUITests: XCTestCase {
|
||||
|
||||
func testOIDC() {
|
||||
// Given the initial login screen.
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.login)
|
||||
let app = Application.launch(.login)
|
||||
|
||||
// When entering a username on a homeserver that only supports OIDC.
|
||||
app.textFields["usernameTextField"].clearAndTypeText("@test:company.com\n")
|
||||
@ -47,13 +45,10 @@ class LoginScreenUITests: XCTestCase {
|
||||
|
||||
func testUnsupported() {
|
||||
// Given the initial login screen.
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.login)
|
||||
let app = Application.launch(.login)
|
||||
|
||||
// When entering a username on a homeserver with an unsupported flow.
|
||||
let usernameTextField = app.textFields["usernameTextField"]
|
||||
XCTAssertTrue(usernameTextField.waitForExistence(timeout: 5.0))
|
||||
usernameTextField.clearAndTypeText("@test:server.net\n")
|
||||
app.textFields["usernameTextField"].clearAndTypeText("@test:server.net\n")
|
||||
|
||||
// Then the screen should not allow login to continue.
|
||||
app.assertScreenshot(.login, step: 2)
|
||||
|
@ -19,15 +19,13 @@ import XCTest
|
||||
@MainActor
|
||||
class OnboardingUITests: XCTestCase {
|
||||
func testInitialStateComponents() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.onboarding)
|
||||
let app = Application.launch(.onboarding)
|
||||
app.assertScreenshot(.onboarding)
|
||||
}
|
||||
|
||||
// This test has been disabled for now as there is only a single page.
|
||||
func disabled_testSwipingBetweenPages() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.onboarding)
|
||||
let app = Application.launch(.onboarding)
|
||||
|
||||
// Given the splash screen in its initial state.
|
||||
let page1TitleText = app.staticTexts[ElementL10n.ftueAuthCarouselSecureTitle]
|
||||
|
@ -19,16 +19,14 @@ import XCTest
|
||||
|
||||
class RoomDetailsScreenUITests: XCTestCase {
|
||||
func testInitialStateComponents() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.roomDetailsScreen)
|
||||
let app = Application.launch(.roomDetailsScreen)
|
||||
|
||||
XCTAssert(app.staticTexts["roomAvatarImage"].exists)
|
||||
app.assertScreenshot(.roomDetailsScreen)
|
||||
}
|
||||
|
||||
func testInitialStateComponentsWithRoomAvatar() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.roomDetailsScreenWithRoomAvatar)
|
||||
let app = Application.launch(.roomDetailsScreenWithRoomAvatar)
|
||||
|
||||
XCTAssert(app.images["roomAvatarImage"].waitForExistence(timeout: 1))
|
||||
app.assertScreenshot(.roomDetailsScreenWithRoomAvatar)
|
||||
|
@ -19,8 +19,7 @@ import XCTest
|
||||
|
||||
class RoomMemberDetailsScreenUITests: XCTestCase {
|
||||
func testInitialStateComponents() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.roomMemberDetailsScreen)
|
||||
let app = Application.launch(.roomMemberDetailsScreen)
|
||||
|
||||
app.assertScreenshot(.roomMemberDetailsScreen)
|
||||
}
|
||||
|
@ -19,9 +19,10 @@ import XCTest
|
||||
|
||||
@MainActor
|
||||
class RoomScreenUITests: XCTestCase {
|
||||
let connectionWaitDuration: Duration = .seconds(2)
|
||||
|
||||
func testPlainNoAvatar() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.roomPlainNoAvatar)
|
||||
let app = Application.launch(.roomPlainNoAvatar)
|
||||
|
||||
XCTAssert(app.staticTexts["roomNameLabel"].exists)
|
||||
XCTAssert(app.staticTexts["roomAvatarImage"].exists)
|
||||
@ -30,8 +31,7 @@ class RoomScreenUITests: XCTestCase {
|
||||
}
|
||||
|
||||
func testEncryptedWithAvatar() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.roomEncryptedWithAvatar)
|
||||
let app = Application.launch(.roomEncryptedWithAvatar)
|
||||
|
||||
XCTAssert(app.staticTexts["roomNameLabel"].exists)
|
||||
XCTAssert(app.images["roomAvatarImage"].waitForExistence(timeout: 1))
|
||||
@ -40,21 +40,19 @@ class RoomScreenUITests: XCTestCase {
|
||||
}
|
||||
|
||||
func testSmallTimelineLayout() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.roomSmallTimeline)
|
||||
let app = Application.launch(.roomSmallTimeline)
|
||||
|
||||
// The messages should be bottom aligned.
|
||||
app.assertScreenshot(.roomSmallTimeline)
|
||||
}
|
||||
|
||||
func testSmallTimelineWithIncomingAndPagination() async throws {
|
||||
func disabled_testSmallTimelineWithIncomingAndPagination() async throws {
|
||||
let listener = try UITestsSignalling.Listener()
|
||||
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.roomSmallTimelineIncomingAndSmallPagination)
|
||||
let app = Application.launch(.roomSmallTimelineIncomingAndSmallPagination)
|
||||
|
||||
let connection = try await listener.connection()
|
||||
try await Task.sleep(for: .seconds(1)) // Allow the connection to settle on CI/Intel...
|
||||
try await Task.sleep(for: connectionWaitDuration) // Allow the connection to settle on CI/Intel...
|
||||
defer { connection.disconnect() }
|
||||
|
||||
// When a back pagination occurs and an incoming message arrives.
|
||||
@ -65,14 +63,13 @@ class RoomScreenUITests: XCTestCase {
|
||||
app.assertScreenshot(.roomSmallTimelineIncomingAndSmallPagination)
|
||||
}
|
||||
|
||||
func testSmallTimelineWithLargePagination() async throws {
|
||||
func disabled_testSmallTimelineWithLargePagination() async throws {
|
||||
let listener = try UITestsSignalling.Listener()
|
||||
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.roomSmallTimelineLargePagination)
|
||||
let app = Application.launch(.roomSmallTimelineLargePagination)
|
||||
|
||||
let connection = try await listener.connection()
|
||||
try await Task.sleep(for: .seconds(1)) // Allow the connection to settle on CI/Intel...
|
||||
try await Task.sleep(for: connectionWaitDuration) // Allow the connection to settle on CI/Intel...
|
||||
defer { connection.disconnect() }
|
||||
|
||||
// When a large back pagination occurs.
|
||||
@ -82,14 +79,13 @@ class RoomScreenUITests: XCTestCase {
|
||||
app.assertScreenshot(.roomSmallTimelineLargePagination)
|
||||
}
|
||||
|
||||
func testTimelineLayoutInMiddle() async throws {
|
||||
func disabled_testTimelineLayoutInMiddle() async throws {
|
||||
let listener = try UITestsSignalling.Listener()
|
||||
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.roomLayoutMiddle)
|
||||
let app = Application.launch(.roomLayoutMiddle)
|
||||
|
||||
let connection = try await listener.connection()
|
||||
try await Task.sleep(for: .seconds(1)) // Allow the connection to settle on CI/Intel...
|
||||
try await Task.sleep(for: connectionWaitDuration) // Allow the connection to settle on CI/Intel...
|
||||
defer { connection.disconnect() }
|
||||
|
||||
// Given a timeline that is neither at the top nor the bottom.
|
||||
@ -116,14 +112,13 @@ class RoomScreenUITests: XCTestCase {
|
||||
app.assertScreenshot(.roomLayoutMiddle, step: 1)
|
||||
}
|
||||
|
||||
func testTimelineLayoutAtTop() async throws {
|
||||
func disabled_testTimelineLayoutAtTop() async throws {
|
||||
let listener = try UITestsSignalling.Listener()
|
||||
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.roomLayoutTop)
|
||||
let app = Application.launch(.roomLayoutTop)
|
||||
|
||||
let connection = try await listener.connection()
|
||||
try await Task.sleep(for: .seconds(1)) // Allow the connection to settle on CI/Intel...
|
||||
try await Task.sleep(for: connectionWaitDuration) // Allow the connection to settle on CI/Intel...
|
||||
defer { connection.disconnect() }
|
||||
|
||||
// Given a timeline that is scrolled to the top.
|
||||
@ -140,14 +135,13 @@ class RoomScreenUITests: XCTestCase {
|
||||
app.assertScreenshot(.roomLayoutTop, insets: cropped)
|
||||
}
|
||||
|
||||
func testTimelineLayoutAtBottom() async throws {
|
||||
func disabled_testTimelineLayoutAtBottom() async throws {
|
||||
let listener = try UITestsSignalling.Listener()
|
||||
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.roomLayoutBottom)
|
||||
let app = Application.launch(.roomLayoutBottom)
|
||||
|
||||
let connection = try await listener.connection()
|
||||
try await Task.sleep(for: .seconds(2)) // Allow the connection to settle on CI/Intel...
|
||||
try await Task.sleep(for: connectionWaitDuration) // Allow the connection to settle on CI/Intel...
|
||||
defer { connection.disconnect() }
|
||||
|
||||
// When an incoming message arrives.
|
||||
@ -168,7 +162,7 @@ class RoomScreenUITests: XCTestCase {
|
||||
private func performOperation(_ operation: UITestsSignal, using connection: UITestsSignalling.Connection) async throws {
|
||||
try await connection.send(operation)
|
||||
guard try await connection.receive() == .success else { throw UITestsSignalError.unexpected }
|
||||
try await Task.sleep(for: .milliseconds(500)) // Allow the timeline to update
|
||||
try await Task.sleep(for: connectionWaitDuration) // Allow the timeline to update, and the connection to be ready
|
||||
}
|
||||
|
||||
private func tapMessageComposer(in app: XCUIApplication) async throws {
|
||||
|
@ -23,8 +23,7 @@ class ServerSelectionUITests: XCTestCase {
|
||||
|
||||
func testNormalState() async {
|
||||
// Given the initial server selection screen as a modal.
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.serverSelection)
|
||||
let app = Application.launch(.serverSelection)
|
||||
|
||||
// Then it should be configured for matrix.org
|
||||
app.assertScreenshot(.serverSelection, step: 0)
|
||||
@ -34,8 +33,7 @@ class ServerSelectionUITests: XCTestCase {
|
||||
|
||||
func testEmptyAddress() async {
|
||||
// Given the initial server selection screen as a modal.
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.serverSelection)
|
||||
let app = Application.launch(.serverSelection)
|
||||
|
||||
// When clearing the server address text field.
|
||||
app.textFields[textFieldIdentifier].tap()
|
||||
@ -49,8 +47,7 @@ class ServerSelectionUITests: XCTestCase {
|
||||
|
||||
func testInvalidAddress() {
|
||||
// Given the initial server selection screen as a modal.
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.serverSelection)
|
||||
let app = Application.launch(.serverSelection)
|
||||
|
||||
// When typing in an invalid homeserver
|
||||
app.textFields[textFieldIdentifier].clearAndTypeText("thisisbad\n") // The tests only accept an address from LoginHomeserver.mockXYZ
|
||||
@ -63,8 +60,7 @@ class ServerSelectionUITests: XCTestCase {
|
||||
|
||||
func testNonModalPresentation() {
|
||||
// Given the initial server selection screen pushed onto the stack.
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.serverSelectionNonModal)
|
||||
let app = Application.launch(.serverSelectionNonModal)
|
||||
|
||||
// Then the screen should be tweaked slightly to reflect the change of navigation.
|
||||
app.assertScreenshot(.serverSelectionNonModal)
|
||||
|
@ -31,8 +31,7 @@ class SessionVerificationUITests: XCTestCase {
|
||||
}
|
||||
|
||||
func testChallengeMatches() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.sessionVerification)
|
||||
let app = Application.launch(.sessionVerification)
|
||||
app.assertScreenshot(.sessionVerification, step: Step.initialState)
|
||||
|
||||
app.buttons["requestVerificationButton"].tap()
|
||||
@ -57,8 +56,7 @@ class SessionVerificationUITests: XCTestCase {
|
||||
}
|
||||
|
||||
func testChallengeDoesNotMatch() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.sessionVerification)
|
||||
let app = Application.launch(.sessionVerification)
|
||||
app.assertScreenshot(.sessionVerification, step: Step.initialState)
|
||||
|
||||
app.buttons["requestVerificationButton"].tap()
|
||||
@ -80,8 +78,7 @@ class SessionVerificationUITests: XCTestCase {
|
||||
}
|
||||
|
||||
func testSessionVerificationCancelation() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.sessionVerification)
|
||||
let app = Application.launch(.sessionVerification)
|
||||
app.assertScreenshot(.sessionVerification, step: Step.initialState)
|
||||
|
||||
app.buttons["requestVerificationButton"].tap()
|
||||
|
@ -17,10 +17,9 @@
|
||||
import ElementX
|
||||
import XCTest
|
||||
|
||||
class SettingsUITests: XCTestCase {
|
||||
class SettingsScreenUITests: XCTestCase {
|
||||
func testInitialStateComponents() {
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.settings)
|
||||
let app = Application.launch(.settings)
|
||||
app.assertScreenshot(.settings)
|
||||
}
|
||||
}
|
||||
|
@ -27,30 +27,16 @@ class SoftLogoutUITests: XCTestCase {
|
||||
}
|
||||
|
||||
func testInitialState() {
|
||||
app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.softLogout)
|
||||
app = Application.launch(.softLogout)
|
||||
|
||||
XCTAssertTrue(app.staticTexts["titleLabel"].exists, "The title should be shown.")
|
||||
XCTAssertTrue(app.staticTexts["messageLabel1"].exists, "The message 1 should be shown.")
|
||||
XCTAssertTrue(app.staticTexts["clearDataTitleLabel"].exists, "The clear data title should be shown.")
|
||||
XCTAssertTrue(app.staticTexts["clearDataMessageLabel"].exists, "The clear data message should be shown.")
|
||||
|
||||
let passwordTextField = app.secureTextFields["passwordTextField"]
|
||||
XCTAssertTrue(passwordTextField.exists, "The password text field should be shown.")
|
||||
XCTAssertTrue(passwordTextField.label.isEmpty, "The password text field text should be empty before text is input.")
|
||||
XCTAssertEqual(passwordTextField.placeholderValue, ElementL10n.loginSignupPasswordHint, "The password text field should be showing the placeholder before text is input.")
|
||||
|
||||
let nextButton = app.buttons["nextButton"]
|
||||
XCTAssertTrue(nextButton.exists, "The next button should be shown.")
|
||||
XCTAssertFalse(nextButton.isEnabled, "The next button should be disabled before text is input.")
|
||||
|
||||
let forgotPasswordButton = app.buttons["forgotPasswordButton"]
|
||||
XCTAssertTrue(forgotPasswordButton.exists, "The forgot password button should be shown.")
|
||||
XCTAssertTrue(forgotPasswordButton.isEnabled, "The forgot password button should be enabled.")
|
||||
|
||||
let clearDataButton = app.buttons["clearDataButton"]
|
||||
XCTAssertTrue(clearDataButton.exists, "The clear data button should be shown.")
|
||||
XCTAssertTrue(clearDataButton.isEnabled, "The clear data button should be enabled.")
|
||||
XCTAssertTrue(app.secureTextFields["passwordTextField"].exists, "The password text field should be shown.")
|
||||
XCTAssertTrue(app.buttons["nextButton"].exists, "The next button should be shown.")
|
||||
XCTAssertTrue(app.buttons["forgotPasswordButton"].exists, "The forgot password button should be shown.")
|
||||
XCTAssertTrue(app.buttons["clearDataButton"].exists, "The clear data button should be shown.")
|
||||
|
||||
app.assertScreenshot(.softLogout)
|
||||
}
|
||||
|
@ -22,8 +22,7 @@ class UserSessionScreenTests: XCTestCase {
|
||||
func testUserSessionFlows() async throws {
|
||||
let roomName = "First room"
|
||||
|
||||
let app = Application.launch()
|
||||
app.goToScreenWithIdentifier(.userSessionScreen)
|
||||
let app = Application.launch(.userSessionScreen)
|
||||
|
||||
app.assertScreenshot(.userSessionScreen, step: 1)
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"defaultTestExecutionTimeAllowance" : 60,
|
||||
"environmentVariableEntries" : [
|
||||
{
|
||||
"key" : "SNAPSHOT_ARTIFACTS",
|
||||
@ -45,12 +46,14 @@
|
||||
"identifier" : "0E28CD62691FDBC63147D5E3",
|
||||
"name" : "UITests"
|
||||
},
|
||||
"testTimeoutsEnabled" : true,
|
||||
"uiTestingScreenshotsLifetime" : "keepNever",
|
||||
"undefinedBehaviorSanitizerEnabled" : true,
|
||||
"userAttachmentLifetime" : "keepNever"
|
||||
},
|
||||
"testTargets" : [
|
||||
{
|
||||
"parallelizable" : true,
|
||||
"target" : {
|
||||
"containerPath" : "container:ElementX.xcodeproj",
|
||||
"identifier" : "0E28CD62691FDBC63147D5E3",
|
||||
|
@ -58,7 +58,7 @@ targets:
|
||||
- "**/__Snapshots__/**"
|
||||
- path: ../SupportingFiles
|
||||
- path: ../../Tools/Scripts/Templates/SimpleScreenExample/Tests/UI
|
||||
- path: ../../ElementX/Sources/UITests/UITestScreenIdentifier.swift
|
||||
- path: ../../ElementX/Sources/UITests/UITestsScreenIdentifier.swift
|
||||
- path: ../../ElementX/Sources/UITests/UITestsSignalling.swift
|
||||
- path: ../../ElementX/Sources/Generated/Strings.swift
|
||||
- path: ../../ElementX/Sources/Generated/Strings+Untranslated.swift
|
||||
|
1
changelog.d/534.change
Normal file
1
changelog.d/534.change
Normal file
@ -0,0 +1 @@
|
||||
Launch UI tests directly in the screen that will be tested and type character by character instead of retrying.
|
Loading…
x
Reference in New Issue
Block a user