mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +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:
@@ -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)
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user