Align accessibility IDs with elementX android (#567)
* Rename onboarding and login user/pass accessibility ids. * Refactor remaining server change accessibility IDs * Avoid accessibilityIdentifier spreading to all decorations on the textBox. Required because otherwise there are multiple items tagged with the accessibilityId which means we can't click on "the" item. * Move all accessibility identifiers to `AccessibilityIdentifiers.swft` - use same naming convention on all of them - remove the unused ones - fix build errors in integration tests and invalid identifiers (still broken until autodiscovery lands on rosa) --------- Co-authored-by: Stefan Ceriu <stefanc@matrix.org>
This commit is contained in:
@@ -21,8 +21,9 @@ import SwiftUI
|
||||
public extension TextFieldStyle where Self == ElementTextFieldStyle {
|
||||
static func elementInput(labelText: String? = nil,
|
||||
footerText: String? = nil,
|
||||
isError: Bool = false) -> ElementTextFieldStyle {
|
||||
ElementTextFieldStyle(labelText: labelText, footerText: footerText, isError: isError)
|
||||
isError: Bool = false,
|
||||
accessibilityIdentifier: String? = nil) -> ElementTextFieldStyle {
|
||||
ElementTextFieldStyle(labelText: labelText, footerText: footerText, isError: isError, accessibilityIdentifier: accessibilityIdentifier)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +39,7 @@ public struct ElementTextFieldStyle: TextFieldStyle {
|
||||
public let labelText: String?
|
||||
public let footerText: String?
|
||||
public let isError: Bool
|
||||
public let accessibilityIdentifier: String?
|
||||
|
||||
/// The color of the text field's border.
|
||||
private var borderColor: Color {
|
||||
@@ -91,10 +93,11 @@ public struct ElementTextFieldStyle: TextFieldStyle {
|
||||
/// - labelText: The text shown in the label above the field.
|
||||
/// - footerText: The text shown in the footer label below the field.
|
||||
/// - isError: Whether or not the text field is currently in the error state.
|
||||
public init(labelText: String? = nil, footerText: String? = nil, isError: Bool = false) {
|
||||
public init(labelText: String? = nil, footerText: String? = nil, isError: Bool = false, accessibilityIdentifier: String? = nil) {
|
||||
self.labelText = labelText
|
||||
self.footerText = footerText
|
||||
self.isError = isError
|
||||
self.accessibilityIdentifier = accessibilityIdentifier
|
||||
}
|
||||
|
||||
public func _body(configuration: TextField<_Label>) -> some View {
|
||||
@@ -128,8 +131,9 @@ public struct ElementTextFieldStyle: TextFieldStyle {
|
||||
textField.clearButtonMode = .whileEditing
|
||||
textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "",
|
||||
attributes: [NSAttributedString.Key.foregroundColor: UIColor(placeholderColor)])
|
||||
textField.accessibilityIdentifier = accessibilityIdentifier
|
||||
}
|
||||
|
||||
|
||||
if let footerText {
|
||||
Text(footerText)
|
||||
.font(.element.caption1)
|
||||
|
||||
89
ElementX/Sources/Other/AccessibilityIdentifiers.swift
Normal file
89
ElementX/Sources/Other/AccessibilityIdentifiers.swift
Normal file
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// Copyright 2023 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 Foundation
|
||||
|
||||
struct A11yIdentifiers {
|
||||
static let bugReportScreen = BugReportScreen()
|
||||
static let changeServerScreen = ChangeServer()
|
||||
static let homeScreen = HomeScreen()
|
||||
static let loginScreen = LoginScreen()
|
||||
static let onboardingScreen = OnboardingScreen()
|
||||
static let roomScreen = RoomScreen()
|
||||
static let sessionVerificationScreen = SessionVerificationScreen()
|
||||
static let softLogoutScreen = SoftLogoutScreen()
|
||||
|
||||
struct BugReportScreen {
|
||||
let report = "bug_report-report"
|
||||
let sendLogs = "bug_report-send_logs"
|
||||
let screenshot = "bug_report-screenshot"
|
||||
let removeScreenshot = "bug_report-remove_screenshot"
|
||||
let send = "bug_report-send"
|
||||
}
|
||||
|
||||
struct ChangeServer {
|
||||
let server = "change_server-server"
|
||||
let `continue` = "change_server-continue"
|
||||
let dismiss = "change_server-dismiss"
|
||||
}
|
||||
|
||||
struct HomeScreen {
|
||||
let userAvatar = "home_screen-user_avatar"
|
||||
|
||||
func roomName(_ name: String) -> String {
|
||||
"home_screen-room_name:\(name)"
|
||||
}
|
||||
}
|
||||
|
||||
struct LoginScreen {
|
||||
let emailUsername = "login-email_username"
|
||||
let password = "login-password"
|
||||
let `continue` = "login-continue"
|
||||
let changeServer = "login-change_server"
|
||||
let oidc = "login-oidc"
|
||||
let unsupportedServer = "login-unsupported_server"
|
||||
}
|
||||
|
||||
struct OnboardingScreen {
|
||||
let signIn = "onboarding-sign_in"
|
||||
let hidden = "onboarding-hidden"
|
||||
}
|
||||
|
||||
struct RoomScreen {
|
||||
let name = "room_name"
|
||||
let avatar = "room_avatar"
|
||||
}
|
||||
|
||||
struct SessionVerificationScreen {
|
||||
let requestVerification = "session_verification-request_verification"
|
||||
let startSasVerification = "session_verification-start_sas_verification"
|
||||
let acceptChallenge = "session_verification-accept_challenge"
|
||||
let declineChallenge = "session_verification-accept_challenge"
|
||||
let close = "session_verification-close"
|
||||
}
|
||||
|
||||
struct SoftLogoutScreen {
|
||||
let title = "soft_logout-title"
|
||||
let message = "soft_logout-message"
|
||||
let password = "soft_logout-password"
|
||||
let forgotPassword = "soft_logout-forgot_password"
|
||||
let next = "soft_logout-next"
|
||||
let unsupportedServer = "soft_logout-unsupported_server"
|
||||
let clearDataTitle = "soft_logout-clear_data_title"
|
||||
let clearDataMessage = "soft_logout-clear_data_message"
|
||||
let clearData = "soft_logout-clear_data"
|
||||
}
|
||||
}
|
||||
@@ -99,14 +99,12 @@ struct AnalyticsPrompt: View {
|
||||
.font(.element.bodyBold)
|
||||
}
|
||||
.buttonStyle(.elementAction(.xLarge))
|
||||
.accessibilityIdentifier("enableButton")
|
||||
|
||||
Button { context.send(viewAction: .disable) } label: {
|
||||
Text(ElementL10n.actionNotNow)
|
||||
.font(.element.bodyBold)
|
||||
.padding(12)
|
||||
}
|
||||
.accessibilityIdentifier("disableButton")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,23 +77,21 @@ struct LoginScreen: View {
|
||||
|
||||
TextField(ElementL10n.loginSigninUsernameHint, text: $context.username)
|
||||
.focused($isUsernameFocused)
|
||||
.textFieldStyle(.elementInput())
|
||||
.textFieldStyle(.elementInput(accessibilityIdentifier: A11yIdentifiers.loginScreen.emailUsername))
|
||||
.disableAutocorrection(true)
|
||||
.textContentType(.username)
|
||||
.autocapitalization(.none)
|
||||
.submitLabel(.next)
|
||||
.onChange(of: isUsernameFocused, perform: usernameFocusChanged)
|
||||
.onSubmit { isPasswordFocused = true }
|
||||
.accessibilityIdentifier("usernameTextField")
|
||||
.padding(.bottom, 20)
|
||||
|
||||
SecureField(ElementL10n.loginSignupPasswordHint, text: $context.password)
|
||||
.focused($isPasswordFocused)
|
||||
.textFieldStyle(.elementInput())
|
||||
.textFieldStyle(.elementInput(accessibilityIdentifier: A11yIdentifiers.loginScreen.password))
|
||||
.textContentType(.password)
|
||||
.submitLabel(.done)
|
||||
.onSubmit(submit)
|
||||
.accessibilityIdentifier("passwordTextField")
|
||||
|
||||
Spacer().frame(height: 32)
|
||||
|
||||
@@ -102,7 +100,7 @@ struct LoginScreen: View {
|
||||
}
|
||||
.buttonStyle(.elementAction(.xLarge))
|
||||
.disabled(!context.viewState.canSubmit)
|
||||
.accessibilityIdentifier("nextButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.loginScreen.continue)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +110,7 @@ struct LoginScreen: View {
|
||||
Text(ElementL10n.loginContinue)
|
||||
}
|
||||
.buttonStyle(.elementAction(.xLarge))
|
||||
.accessibilityIdentifier("oidcButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.loginScreen.oidc)
|
||||
}
|
||||
|
||||
/// Text shown if neither password or OIDC login is supported.
|
||||
@@ -122,7 +120,7 @@ struct LoginScreen: View {
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.frame(maxWidth: .infinity)
|
||||
.accessibilityIdentifier("unsupportedServerText")
|
||||
.accessibilityIdentifier(A11yIdentifiers.loginScreen.unsupportedServer)
|
||||
}
|
||||
|
||||
/// Parses the username for a homeserver.
|
||||
|
||||
@@ -51,7 +51,7 @@ struct LoginServerInfoSection: View {
|
||||
}
|
||||
.background(RoundedRectangle(cornerRadius: 14).fill(Color.element.system))
|
||||
}
|
||||
.accessibilityIdentifier("editServerButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.loginScreen.changeServer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,21 +62,21 @@ struct ServerSelectionScreen: View {
|
||||
TextField(ElementL10n.ftueAuthChooseServerEntryHint, text: $context.homeserverAddress)
|
||||
.textFieldStyle(.elementInput(labelText: ElementL10n.hsUrl,
|
||||
footerText: context.viewState.footerMessage,
|
||||
isError: context.viewState.isShowingFooterError))
|
||||
isError: context.viewState.isShowingFooterError,
|
||||
accessibilityIdentifier: A11yIdentifiers.changeServerScreen.server))
|
||||
.keyboardType(.URL)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.onChange(of: context.homeserverAddress) { _ in context.send(viewAction: .clearFooterError) }
|
||||
.submitLabel(.done)
|
||||
.onSubmit(submit)
|
||||
.accessibilityIdentifier("addressTextField")
|
||||
|
||||
Button(action: submit) {
|
||||
Text(context.viewState.buttonTitle)
|
||||
}
|
||||
.buttonStyle(.elementAction(.xLarge))
|
||||
.disabled(context.viewState.hasValidationError)
|
||||
.accessibilityIdentifier("confirmButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.changeServerScreen.continue)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ struct ServerSelectionScreen: View {
|
||||
Button { context.send(viewAction: .dismiss) } label: {
|
||||
Text(ElementL10n.actionCancel)
|
||||
}
|
||||
.accessibilityIdentifier("dismissButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.changeServerScreen.dismiss)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,20 +58,19 @@ struct SoftLogoutScreen: View {
|
||||
.font(.element.title2Bold)
|
||||
.multilineTextAlignment(.leading)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.accessibilityIdentifier("titleLabel")
|
||||
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.title)
|
||||
|
||||
Text(ElementL10n.softLogoutSigninNotice(context.viewState.credentials.homeserverName, context.viewState.credentials.userDisplayName, context.viewState.credentials.userId))
|
||||
.font(.element.body)
|
||||
.multilineTextAlignment(.leading)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.accessibilityIdentifier("messageLabel1")
|
||||
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.message)
|
||||
|
||||
if context.viewState.showRecoverEncryptionKeysMessage {
|
||||
Text(ElementL10n.softLogoutSigninE2eWarningNotice)
|
||||
.font(.element.body)
|
||||
.multilineTextAlignment(.leading)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.accessibilityIdentifier("messageLabel2")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,7 +84,7 @@ struct SoftLogoutScreen: View {
|
||||
.textContentType(.password)
|
||||
.submitLabel(.done)
|
||||
.onSubmit(submit)
|
||||
.accessibilityIdentifier("passwordTextField")
|
||||
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.password)
|
||||
|
||||
Button { context.send(viewAction: .forgotPassword) } label: {
|
||||
Text(ElementL10n.ftueAuthForgotPassword)
|
||||
@@ -93,14 +92,14 @@ struct SoftLogoutScreen: View {
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
||||
.padding(.bottom, 8)
|
||||
.accessibilityIdentifier("forgotPasswordButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.forgotPassword)
|
||||
|
||||
Button(action: submit) {
|
||||
Text(ElementL10n.loginSignupSubmit)
|
||||
}
|
||||
.buttonStyle(.elementAction(.xLarge))
|
||||
.disabled(!context.viewState.canSubmit)
|
||||
.accessibilityIdentifier("nextButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.next)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +109,6 @@ struct SoftLogoutScreen: View {
|
||||
Text(ElementL10n.loginContinue)
|
||||
}
|
||||
.buttonStyle(.elementAction(.xLarge))
|
||||
.accessibilityIdentifier("oidcButton")
|
||||
}
|
||||
|
||||
/// Text shown if neither password or OIDC login is supported.
|
||||
@@ -120,7 +118,6 @@ struct SoftLogoutScreen: View {
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.frame(maxWidth: .infinity)
|
||||
.accessibilityIdentifier("unsupportedServerText")
|
||||
}
|
||||
|
||||
/// The text field and submit button where the user enters an email address.
|
||||
@@ -130,20 +127,20 @@ struct SoftLogoutScreen: View {
|
||||
.font(.element.title2Bold)
|
||||
.multilineTextAlignment(.leading)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.accessibilityIdentifier("clearDataTitleLabel")
|
||||
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.clearDataTitle)
|
||||
|
||||
Text(ElementL10n.softLogoutClearDataNotice)
|
||||
.font(.element.body)
|
||||
.multilineTextAlignment(.leading)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.accessibilityIdentifier("clearDataMessageLabel")
|
||||
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.clearDataMessage)
|
||||
.padding(.bottom, 12)
|
||||
|
||||
Button(action: clearData) {
|
||||
Text(ElementL10n.softLogoutClearDataSubmit)
|
||||
}
|
||||
.buttonStyle(.elementAction(.xLarge, color: .element.alert))
|
||||
.accessibilityIdentifier("clearDataButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.softLogoutScreen.clearData)
|
||||
.alert(ElementL10n.softLogoutClearDataDialogTitle,
|
||||
isPresented: $showingClearDataConfirmation) {
|
||||
Button(ElementL10n.actionSignOut,
|
||||
|
||||
@@ -59,7 +59,7 @@ struct BugReportScreen: View {
|
||||
.padding(.horizontal, 10)
|
||||
.padding(.vertical, 4)
|
||||
.cornerRadius(14)
|
||||
.accessibilityIdentifier("reportTextView")
|
||||
.accessibilityIdentifier(A11yIdentifiers.bugReportScreen.report)
|
||||
.scrollContentBackground(.hidden)
|
||||
|
||||
if context.reportText.isEmpty {
|
||||
@@ -84,7 +84,7 @@ struct BugReportScreen: View {
|
||||
VStack(spacing: 8) {
|
||||
Toggle(ElementL10n.bugReportScreenIncludeLogs, isOn: $context.sendingLogsEnabled)
|
||||
.tint(Color.element.brand)
|
||||
.accessibilityIdentifier("sendLogsToggle")
|
||||
.accessibilityIdentifier(A11yIdentifiers.bugReportScreen.sendLogs)
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 11)
|
||||
.background(RoundedRectangle(cornerRadius: 14).fill(Color.element.formRowBackground))
|
||||
@@ -104,12 +104,12 @@ struct BugReportScreen: View {
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 100)
|
||||
.accessibilityIdentifier("screenshotImage")
|
||||
.accessibilityIdentifier(A11yIdentifiers.bugReportScreen.screenshot)
|
||||
Button { context.send(viewAction: .removeScreenshot) } label: {
|
||||
Image(uiImage: Asset.Images.closeCircle.image)
|
||||
}
|
||||
.offset(x: 10, y: -10)
|
||||
.accessibilityIdentifier("removeScreenshotButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.bugReportScreen.removeScreenshot)
|
||||
}
|
||||
.padding(.vertical, 16)
|
||||
.padding(.horizontal, 16)
|
||||
@@ -131,7 +131,7 @@ struct BugReportScreen: View {
|
||||
context.send(viewAction: .submit)
|
||||
}
|
||||
.disabled(context.reportText.count < 5)
|
||||
.accessibilityIdentifier("sendButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.bugReportScreen.send)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ struct EmojiPickerScreen: View {
|
||||
Button { context.send(viewAction: .dismiss) } label: {
|
||||
Text(ElementL10n.actionCancel)
|
||||
}
|
||||
.accessibilityIdentifier("dismissButton")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ struct HomeScreen: View {
|
||||
contentID: context.viewState.userID,
|
||||
avatarSize: .user(on: .home),
|
||||
imageProvider: context.imageProvider)
|
||||
.accessibilityIdentifier("userAvatarImage")
|
||||
.accessibilityIdentifier(A11yIdentifiers.homeScreen.userAvatar)
|
||||
}
|
||||
.alert(ElementL10n.actionSignOut,
|
||||
isPresented: $showingLogoutConfirmation) {
|
||||
|
||||
@@ -38,7 +38,7 @@ struct HomeScreenRoomCell: View {
|
||||
.accessibilityElement(children: .combine)
|
||||
}
|
||||
.buttonStyle(HomeScreenRoomCellButtonStyle())
|
||||
.accessibilityIdentifier("roomName:\(room.name)")
|
||||
.accessibilityIdentifier(A11yIdentifiers.homeScreen.roomName(room.name))
|
||||
.overlay(alignment: .bottom) {
|
||||
Divider()
|
||||
.frame(height: 0.5)
|
||||
|
||||
@@ -47,7 +47,7 @@ struct OnboardingScreen: View {
|
||||
// Add a hidden page at the start of the carousel duplicating the content of the last page
|
||||
OnboardingPageView(content: context.viewState.content[pageCount - 1])
|
||||
.frame(width: geometry.size.width)
|
||||
.accessibilityIdentifier("hiddenPage")
|
||||
.accessibilityIdentifier(A11yIdentifiers.onboardingScreen.hidden)
|
||||
|
||||
ForEach(0..<pageCount, id: \.self) { index in
|
||||
OnboardingPageView(content: context.viewState.content[index])
|
||||
@@ -93,7 +93,7 @@ struct OnboardingScreen: View {
|
||||
Text(ElementL10n.loginContinue)
|
||||
}
|
||||
.buttonStyle(.elementAction(.xLarge))
|
||||
.accessibilityIdentifier("getStartedButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.onboardingScreen.signIn)
|
||||
}
|
||||
.padding(.horizontal, verticalSizeClass == .compact ? 128 : 24)
|
||||
.readableFrame()
|
||||
|
||||
@@ -53,7 +53,6 @@ struct RoomDetailsScreen: View {
|
||||
contentID: context.viewState.roomId,
|
||||
avatarSize: .room(on: .details),
|
||||
imageProvider: context.imageProvider)
|
||||
.accessibilityIdentifier("roomAvatarImage")
|
||||
|
||||
Text(context.viewState.title)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
@@ -129,7 +128,6 @@ struct RoomDetailsScreen: View {
|
||||
}
|
||||
.listRowInsets(listRowInsets)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.accessibilityIdentifier("peopleButton")
|
||||
.disabled(context.viewState.isLoadingMembers)
|
||||
} header: {
|
||||
Text(ElementL10n.roomDetailsAboutSectionTitle)
|
||||
|
||||
@@ -29,7 +29,7 @@ struct RoomHeaderView: View {
|
||||
.accessibilityHidden(true)
|
||||
Text(context.viewState.roomTitle)
|
||||
.font(.element.headline)
|
||||
.accessibilityIdentifier("roomNameLabel")
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.name)
|
||||
}
|
||||
// Leading align whilst using the principal toolbar position.
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
@@ -45,7 +45,7 @@ struct RoomHeaderView: View {
|
||||
contentID: context.viewState.roomId,
|
||||
avatarSize: .room(on: .timeline),
|
||||
imageProvider: context.imageProvider)
|
||||
.accessibilityIdentifier("roomAvatarImage")
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.avatar)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,14 +79,12 @@ struct SessionVerificationScreen: View {
|
||||
.font(.title2.bold())
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
.accessibilityIdentifier("titleLabel")
|
||||
.padding(.bottom, 8)
|
||||
|
||||
Text(context.viewState.message)
|
||||
.font(.subheadline)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.element.tertiaryContent)
|
||||
.accessibilityIdentifier("detailLabel")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,21 +127,20 @@ struct SessionVerificationScreen: View {
|
||||
context.send(viewAction: .requestVerification)
|
||||
}
|
||||
.buttonStyle(.elementAction(.xLarge))
|
||||
.accessibilityIdentifier("requestVerificationButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.requestVerification)
|
||||
|
||||
case .cancelled:
|
||||
Button(ElementL10n.globalRetry) {
|
||||
context.send(viewAction: .restart)
|
||||
}
|
||||
.buttonStyle(.elementAction(.xLarge))
|
||||
.accessibilityIdentifier("restartButton")
|
||||
|
||||
case .verificationRequestAccepted:
|
||||
Button(ElementL10n.sessionVerificationStart) {
|
||||
context.send(viewAction: .startSasVerification)
|
||||
}
|
||||
.buttonStyle(.elementAction(.xLarge))
|
||||
.accessibilityIdentifier("sasVerificationStartButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.startSasVerification)
|
||||
|
||||
case .showingChallenge:
|
||||
VStack(spacing: 30) {
|
||||
@@ -151,13 +148,13 @@ struct SessionVerificationScreen: View {
|
||||
Label(ElementL10n.verificationSasMatch, systemImage: "checkmark")
|
||||
}
|
||||
.buttonStyle(.elementAction(.xLarge))
|
||||
.accessibilityIdentifier("challengeAcceptButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.acceptChallenge)
|
||||
|
||||
Button(ElementL10n.verificationSasDoNotMatch) {
|
||||
context.send(viewAction: .decline)
|
||||
}
|
||||
.font(.element.bodyBold)
|
||||
.accessibilityIdentifier("challengeDeclineButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.declineChallenge)
|
||||
}
|
||||
|
||||
case .acceptingChallenge:
|
||||
@@ -170,14 +167,14 @@ struct SessionVerificationScreen: View {
|
||||
}
|
||||
}
|
||||
.buttonStyle(.elementAction(.xLarge))
|
||||
.accessibilityIdentifier("challengeAcceptButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.acceptChallenge)
|
||||
.disabled(true)
|
||||
|
||||
Button(ElementL10n.verificationSasDoNotMatch) {
|
||||
context.send(viewAction: .decline)
|
||||
}
|
||||
.font(.element.bodyBold)
|
||||
.accessibilityIdentifier("challengeDeclineButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.declineChallenge)
|
||||
.disabled(true)
|
||||
}
|
||||
|
||||
@@ -193,7 +190,7 @@ struct SessionVerificationScreen: View {
|
||||
context.send(viewAction: .close)
|
||||
}
|
||||
.foregroundColor(.element.accent)
|
||||
.accessibilityIdentifier("closeButton")
|
||||
.accessibilityIdentifier(A11yIdentifiers.sessionVerificationScreen.close)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,6 @@ struct SettingsScreen: View {
|
||||
image: Image(systemName: "checkmark.shield")) {
|
||||
context.send(viewAction: .sessionVerification)
|
||||
}
|
||||
.accessibilityIdentifier("sessionVerificationButton")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +146,6 @@ struct SettingsScreen: View {
|
||||
|
||||
private var doneButton: some View {
|
||||
Button(ElementL10n.done, action: close)
|
||||
.accessibilityIdentifier("closeButton")
|
||||
}
|
||||
|
||||
private func close() {
|
||||
|
||||
@@ -38,46 +38,41 @@ class LoginTests: XCTestCase {
|
||||
private func runLoginLogoutFlow() {
|
||||
let app = Application.launch()
|
||||
|
||||
let getStartedButton = app.buttons["Get started"]
|
||||
let getStartedButton = app.buttons[A11yIdentifiers.onboarding.signIn]
|
||||
|
||||
XCTAssertTrue(getStartedButton.waitForExistence(timeout: 5.0))
|
||||
getStartedButton.tap()
|
||||
|
||||
let editHomeserverButton = app.buttons["editServerButton"]
|
||||
let editHomeserverButton = app.buttons[A11yIdentifiers.loginScreen.changeServer]
|
||||
XCTAssertTrue(editHomeserverButton.waitForExistence(timeout: 5.0))
|
||||
editHomeserverButton.tap()
|
||||
|
||||
let homeserverTextField = app.textFields["addressTextField"]
|
||||
let homeserverTextField = app.textFields[A11yIdentifiers.changeServer.server]
|
||||
XCTAssertTrue(homeserverTextField.waitForExistence(timeout: 5.0))
|
||||
|
||||
homeserverTextField.clearAndTypeText(app.homeserver)
|
||||
|
||||
let slidingSyncTextField = app.textFields["slidingSyncProxyAddressTextField"]
|
||||
XCTAssertTrue(slidingSyncTextField.waitForExistence(timeout: 5.0))
|
||||
|
||||
slidingSyncTextField.clearAndTypeText(app.homeserver)
|
||||
|
||||
let confirmButton = app.buttons["confirmButton"]
|
||||
|
||||
let confirmButton = app.buttons[A11yIdentifiers.changeServer.server]
|
||||
XCTAssertTrue(confirmButton.exists)
|
||||
confirmButton.tap()
|
||||
|
||||
let usernameTextField = app.textFields["usernameTextField"]
|
||||
let usernameTextField = app.textFields[A11yIdentifiers.loginScreen.emailUsername]
|
||||
XCTAssertTrue(usernameTextField.exists)
|
||||
|
||||
usernameTextField.clearAndTypeText(app.username)
|
||||
|
||||
let passwordTextField = app.secureTextFields["passwordTextField"]
|
||||
let passwordTextField = app.secureTextFields[A11yIdentifiers.loginScreen.password]
|
||||
XCTAssertTrue(passwordTextField.exists)
|
||||
|
||||
passwordTextField.clearAndTypeText(app.password)
|
||||
|
||||
let nextButton = app.buttons["nextButton"]
|
||||
let nextButton = app.buttons[A11yIdentifiers.loginScreen.continue]
|
||||
XCTAssertTrue(nextButton.exists)
|
||||
XCTAssertTrue(nextButton.isEnabled)
|
||||
|
||||
nextButton.tap()
|
||||
|
||||
let profileButton = app.buttons["userAvatarImage"]
|
||||
let profileButton = app.buttons[A11yIdentifiers.homeScreen.userAvatar]
|
||||
XCTAssertTrue(profileButton.waitForExistence(timeout: expectedDuration))
|
||||
profileButton.tap()
|
||||
|
||||
|
||||
@@ -58,4 +58,6 @@ targets:
|
||||
sources:
|
||||
- path: ../Sources
|
||||
- path: ../SupportingFiles
|
||||
- path: ../../ElementX/Sources/Other/AccessibilityIdentifiers.swift
|
||||
- path: ../../ElementX/Sources/Other/Extensions/XCUIElement.swift
|
||||
- path: ../../ElementX/Sources/Other/Extensions/NSRegularExpresion.swift
|
||||
|
||||
@@ -25,17 +25,17 @@ class AuthenticationCoordinatorUITests: XCTestCase {
|
||||
let app = Application.launch(.authenticationFlow)
|
||||
|
||||
// Splash Screen: Tap get started button
|
||||
app.buttons["getStartedButton"].tap()
|
||||
app.buttons[A11yIdentifiers.onboardingScreen.signIn].tap()
|
||||
|
||||
// Login Screen: Enter valid credentials
|
||||
|
||||
app.textFields["usernameTextField"].clearAndTypeText("alice\n")
|
||||
app.secureTextFields["passwordTextField"].clearAndTypeText("12345678")
|
||||
app.textFields[A11yIdentifiers.loginScreen.emailUsername].clearAndTypeText("alice\n")
|
||||
app.secureTextFields[A11yIdentifiers.loginScreen.password].clearAndTypeText("12345678")
|
||||
|
||||
app.assertScreenshot(.authenticationFlow)
|
||||
|
||||
// Login Screen: Tap next
|
||||
app.buttons["nextButton"].tap()
|
||||
app.buttons[A11yIdentifiers.loginScreen.continue].tap()
|
||||
|
||||
// Then login should succeed.
|
||||
XCTAssertFalse(app.alerts.element.exists, "No alert should be shown when logging in with valid credentials.")
|
||||
@@ -46,14 +46,14 @@ class AuthenticationCoordinatorUITests: XCTestCase {
|
||||
let app = Application.launch(.authenticationFlow)
|
||||
|
||||
// Splash Screen: Tap get started button
|
||||
app.buttons["getStartedButton"].tap()
|
||||
app.buttons[A11yIdentifiers.onboardingScreen.signIn].tap()
|
||||
|
||||
// Login Screen: Enter invalid credentials
|
||||
app.textFields["usernameTextField"].clearAndTypeText("alice")
|
||||
app.secureTextFields["passwordTextField"].clearAndTypeText("87654321")
|
||||
app.textFields[A11yIdentifiers.loginScreen.emailUsername].clearAndTypeText("alice")
|
||||
app.secureTextFields[A11yIdentifiers.loginScreen.password].clearAndTypeText("87654321")
|
||||
|
||||
// Login Screen: Tap next
|
||||
let nextButton = app.buttons["nextButton"]
|
||||
let nextButton = app.buttons[A11yIdentifiers.loginScreen.continue]
|
||||
XCTAssertTrue(nextButton.waitForExistence(timeout: 2.0))
|
||||
XCTAssertTrue(nextButton.isEnabled)
|
||||
nextButton.tap()
|
||||
@@ -67,19 +67,19 @@ class AuthenticationCoordinatorUITests: XCTestCase {
|
||||
let app = Application.launch(.authenticationFlow)
|
||||
|
||||
// Splash Screen: Tap get started button
|
||||
app.buttons["getStartedButton"].tap()
|
||||
app.buttons[A11yIdentifiers.onboardingScreen.signIn].tap()
|
||||
|
||||
// Login Screen: Tap edit server button.
|
||||
XCTAssertFalse(app.buttons["oidcButton"].exists, "The OIDC button shouldn't be shown before entering a supported homeserver.")
|
||||
app.buttons["editServerButton"].tap()
|
||||
XCTAssertFalse(app.buttons[A11yIdentifiers.loginScreen.oidc].exists, "The OIDC button shouldn't be shown before entering a supported homeserver.")
|
||||
app.buttons[A11yIdentifiers.loginScreen.changeServer].tap()
|
||||
|
||||
// Server Selection: Clear the default and enter OIDC server.
|
||||
app.textFields["addressTextField"].clearAndTypeText("company.com")
|
||||
app.textFields[A11yIdentifiers.changeServerScreen.server].clearAndTypeText("company.com")
|
||||
|
||||
// Dismiss server screen.
|
||||
app.buttons["confirmButton"].tap()
|
||||
app.buttons[A11yIdentifiers.changeServerScreen.continue].tap()
|
||||
|
||||
// Then the login form should be updated for OIDC.
|
||||
XCTAssertTrue(app.buttons["oidcButton"].waitForExistence(timeout: 1), "The OIDC button should be shown after selecting a homeserver with OIDC.")
|
||||
XCTAssertTrue(app.buttons[A11yIdentifiers.loginScreen.oidc].waitForExistence(timeout: 1), "The OIDC button should be shown after selecting a homeserver with OIDC.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ class BugReportUITests: XCTestCase {
|
||||
func testToggleSendingLogs() {
|
||||
let app = Application.launch(.bugReport)
|
||||
|
||||
app.switches["sendLogsToggle"].tap()
|
||||
app.switches[A11yIdentifiers.bugReportScreen.sendLogs].tap()
|
||||
|
||||
let sendingLogsToggle = app.switches["sendLogsToggle"]
|
||||
let sendingLogsToggle = app.switches[A11yIdentifiers.bugReportScreen.sendLogs]
|
||||
XCTAssert(sendingLogsToggle.exists)
|
||||
XCTAssertFalse(sendingLogsToggle.isOn)
|
||||
|
||||
@@ -41,13 +41,13 @@ class BugReportUITests: XCTestCase {
|
||||
let app = Application.launch(.bugReport)
|
||||
|
||||
// Type 4 characters and the send button should be disabled.
|
||||
app.textViews["reportTextView"].clearAndTypeText("Text")
|
||||
XCTAssertFalse(app.buttons["sendButton"].isEnabled)
|
||||
app.textViews[A11yIdentifiers.bugReportScreen.report].clearAndTypeText("Text")
|
||||
XCTAssertFalse(app.buttons[A11yIdentifiers.bugReportScreen.send].isEnabled)
|
||||
app.assertScreenshot(.bugReport, step: 2)
|
||||
|
||||
// Type more than 4 characters and send the button should become enabled.
|
||||
app.textViews["reportTextView"].clearAndTypeText("Longer text")
|
||||
XCTAssert(app.buttons["sendButton"].isEnabled)
|
||||
app.textViews[A11yIdentifiers.bugReportScreen.report].clearAndTypeText("Longer text")
|
||||
XCTAssert(app.buttons[A11yIdentifiers.bugReportScreen.send].isEnabled)
|
||||
app.assertScreenshot(.bugReport, step: 3)
|
||||
}
|
||||
|
||||
@@ -55,8 +55,8 @@ class BugReportUITests: XCTestCase {
|
||||
let app = Application.launch(.bugReportWithScreenshot)
|
||||
|
||||
// Initial state with a screenshot attached.
|
||||
XCTAssert(app.images["screenshotImage"].exists)
|
||||
XCTAssert(app.buttons["removeScreenshotButton"].exists)
|
||||
XCTAssert(app.images[A11yIdentifiers.bugReportScreen.screenshot].exists)
|
||||
XCTAssert(app.buttons[A11yIdentifiers.bugReportScreen.removeScreenshot].exists)
|
||||
app.assertScreenshot(.bugReportWithScreenshot)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ class LoginScreenUITests: XCTestCase {
|
||||
app.assertScreenshot(.login)
|
||||
|
||||
// When typing in a username and password.
|
||||
app.textFields["usernameTextField"].clearAndTypeText("@test:matrix.org")
|
||||
app.secureTextFields["passwordTextField"].clearAndTypeText("12345678")
|
||||
app.textFields[A11yIdentifiers.loginScreen.emailUsername].clearAndTypeText("@test:matrix.org")
|
||||
app.secureTextFields[A11yIdentifiers.loginScreen.password].clearAndTypeText("12345678")
|
||||
|
||||
// Then the form should be ready to submit.
|
||||
app.assertScreenshot(.login, step: 0)
|
||||
@@ -37,7 +37,7 @@ class LoginScreenUITests: XCTestCase {
|
||||
let app = Application.launch(.login)
|
||||
|
||||
// When entering a username on a homeserver that only supports OIDC.
|
||||
app.textFields["usernameTextField"].clearAndTypeText("@test:company.com\n")
|
||||
app.textFields[A11yIdentifiers.loginScreen.emailUsername].clearAndTypeText("@test:company.com\n")
|
||||
|
||||
// Then the screen should be configured for OIDC.
|
||||
app.assertScreenshot(.login, step: 1)
|
||||
@@ -48,7 +48,7 @@ class LoginScreenUITests: XCTestCase {
|
||||
let app = Application.launch(.login)
|
||||
|
||||
// When entering a username on a homeserver with an unsupported flow.
|
||||
app.textFields["usernameTextField"].clearAndTypeText("@test:server.net\n")
|
||||
app.textFields[A11yIdentifiers.loginScreen.emailUsername].clearAndTypeText("@test:server.net\n")
|
||||
|
||||
// Then the screen should not allow login to continue.
|
||||
app.assertScreenshot(.login, step: 2)
|
||||
|
||||
@@ -30,7 +30,7 @@ class OnboardingUITests: XCTestCase {
|
||||
// Given the splash screen in its initial state.
|
||||
let page1TitleText = app.staticTexts[ElementL10n.ftueAuthCarouselSecureTitle]
|
||||
let page2TitleText = app.staticTexts[ElementL10n.ftueAuthCarouselControlTitle]
|
||||
let hiddenPageTitleText = app.staticTexts["hiddenPage"].firstMatch
|
||||
let hiddenPageTitleText = app.staticTexts[A11yIdentifiers.onboardingScreen.hidden].firstMatch
|
||||
|
||||
XCTAssertTrue(page1TitleText.isHittable, "The title from the first page of the carousel should be onscreen.")
|
||||
XCTAssertFalse(page2TitleText.isHittable, "The title from the second page of the carousel should be offscreen.")
|
||||
|
||||
@@ -21,14 +21,14 @@ class RoomDetailsScreenUITests: XCTestCase {
|
||||
func testInitialStateComponents() {
|
||||
let app = Application.launch(.roomDetailsScreen)
|
||||
|
||||
XCTAssert(app.staticTexts["roomAvatarImage"].exists)
|
||||
XCTAssert(app.staticTexts[A11yIdentifiers.roomScreen.avatar].exists)
|
||||
app.assertScreenshot(.roomDetailsScreen)
|
||||
}
|
||||
|
||||
func testInitialStateComponentsWithRoomAvatar() {
|
||||
let app = Application.launch(.roomDetailsScreenWithRoomAvatar)
|
||||
|
||||
XCTAssert(app.images["roomAvatarImage"].waitForExistence(timeout: 1))
|
||||
XCTAssert(app.images[A11yIdentifiers.roomScreen.avatar].waitForExistence(timeout: 1))
|
||||
app.assertScreenshot(.roomDetailsScreenWithRoomAvatar)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ class RoomScreenUITests: XCTestCase {
|
||||
func testPlainNoAvatar() {
|
||||
let app = Application.launch(.roomPlainNoAvatar)
|
||||
|
||||
XCTAssert(app.staticTexts["roomNameLabel"].exists)
|
||||
XCTAssert(app.staticTexts["roomAvatarImage"].exists)
|
||||
XCTAssert(app.staticTexts[A11yIdentifiers.roomScreen.name].exists)
|
||||
XCTAssert(app.staticTexts[A11yIdentifiers.roomScreen.avatar].exists)
|
||||
|
||||
app.assertScreenshot(.roomPlainNoAvatar)
|
||||
}
|
||||
@@ -33,8 +33,8 @@ class RoomScreenUITests: XCTestCase {
|
||||
func testEncryptedWithAvatar() {
|
||||
let app = Application.launch(.roomEncryptedWithAvatar)
|
||||
|
||||
XCTAssert(app.staticTexts["roomNameLabel"].exists)
|
||||
XCTAssert(app.images["roomAvatarImage"].waitForExistence(timeout: 1))
|
||||
XCTAssert(app.staticTexts[A11yIdentifiers.roomScreen.name].exists)
|
||||
XCTAssert(app.images[A11yIdentifiers.roomScreen.avatar].waitForExistence(timeout: 1))
|
||||
|
||||
app.assertScreenshot(.roomEncryptedWithAvatar)
|
||||
}
|
||||
|
||||
@@ -19,16 +19,14 @@ import XCTest
|
||||
|
||||
@MainActor
|
||||
class ServerSelectionUITests: XCTestCase {
|
||||
let textFieldIdentifier = "addressTextField"
|
||||
|
||||
func testNormalState() async {
|
||||
// Given the initial server selection screen as a modal.
|
||||
let app = Application.launch(.serverSelection)
|
||||
|
||||
// Then it should be configured for matrix.org
|
||||
app.assertScreenshot(.serverSelection, step: 0)
|
||||
XCTAssertEqual(app.textFields[textFieldIdentifier].value as? String, "matrix.org", "The server shown should be matrix.org with the https scheme hidden.")
|
||||
XCTAssertEqual(app.buttons["confirmButton"].label, ElementL10n.continue, "The confirm button should say Confirm when in modal presentation.")
|
||||
XCTAssertEqual(app.textFields[A11yIdentifiers.changeServerScreen.server].value as? String, "matrix.org", "The server shown should be matrix.org with the https scheme hidden.")
|
||||
XCTAssertEqual(app.buttons[A11yIdentifiers.changeServerScreen.continue].label, ElementL10n.continue, "The confirm button should say Confirm when in modal presentation.")
|
||||
}
|
||||
|
||||
func testEmptyAddress() async {
|
||||
@@ -36,13 +34,13 @@ class ServerSelectionUITests: XCTestCase {
|
||||
let app = Application.launch(.serverSelection)
|
||||
|
||||
// When clearing the server address text field.
|
||||
app.textFields[textFieldIdentifier].tap()
|
||||
app.textFields[textFieldIdentifier].buttons.element.tap()
|
||||
app.textFields[A11yIdentifiers.changeServerScreen.server].tap()
|
||||
app.textFields[A11yIdentifiers.changeServerScreen.server].buttons.element.tap()
|
||||
|
||||
// Then the screen should not allow the user to continue.
|
||||
app.assertScreenshot(.serverSelection, step: 1)
|
||||
XCTAssertEqual(app.textFields[textFieldIdentifier].value as? String, ElementL10n.ftueAuthChooseServerEntryHint, "The text field should show placeholder text in this state.")
|
||||
XCTAssertFalse(app.buttons["confirmButton"].isEnabled, "The confirm button should be disabled when the address is empty.")
|
||||
XCTAssertEqual(app.textFields[A11yIdentifiers.changeServerScreen.server].value as? String, ElementL10n.ftueAuthChooseServerEntryHint, "The text field should show placeholder text in this state.")
|
||||
XCTAssertFalse(app.buttons[A11yIdentifiers.changeServerScreen.continue].isEnabled, "The confirm button should be disabled when the address is empty.")
|
||||
}
|
||||
|
||||
func testInvalidAddress() {
|
||||
@@ -50,12 +48,12 @@ class ServerSelectionUITests: XCTestCase {
|
||||
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
|
||||
app.textFields[A11yIdentifiers.changeServerScreen.server].clearAndTypeText("thisisbad\n") // The tests only accept an address from LoginHomeserver.mockXYZ
|
||||
|
||||
// Then an error should be shown and the confirmation button disabled.
|
||||
app.assertScreenshot(.serverSelection, step: 2)
|
||||
XCTAssertTrue(app.staticTexts[ElementL10n.loginErrorHomeserverNotFound].exists)
|
||||
XCTAssertFalse(app.buttons["confirmButton"].isEnabled, "The confirm button should be disabled when there is an error.")
|
||||
XCTAssertFalse(app.buttons[A11yIdentifiers.changeServerScreen.continue].isEnabled, "The confirm button should be disabled when there is an error.")
|
||||
}
|
||||
|
||||
func testNonModalPresentation() {
|
||||
@@ -64,7 +62,7 @@ class ServerSelectionUITests: XCTestCase {
|
||||
|
||||
// Then the screen should be tweaked slightly to reflect the change of navigation.
|
||||
app.assertScreenshot(.serverSelectionNonModal)
|
||||
XCTAssertFalse(app.buttons["dismissButton"].exists, "The dismiss button should be hidden when not in modal presentation.")
|
||||
XCTAssertEqual(app.buttons["confirmButton"].label, ElementL10n.actionNext, "The confirm button should say Next when not in modal presentation.")
|
||||
XCTAssertFalse(app.buttons[A11yIdentifiers.changeServerScreen.dismiss].exists, "The dismiss button should be hidden when not in modal presentation.")
|
||||
XCTAssertEqual(app.buttons[A11yIdentifiers.changeServerScreen.continue].label, ElementL10n.actionNext, "The confirm button should say Next when not in modal presentation.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,68 +34,68 @@ class SessionVerificationUITests: XCTestCase {
|
||||
let app = Application.launch(.sessionVerification)
|
||||
app.assertScreenshot(.sessionVerification, step: Step.initialState)
|
||||
|
||||
app.buttons["requestVerificationButton"].tap()
|
||||
app.buttons[A11yIdentifiers.sessionVerificationScreen.requestVerification].tap()
|
||||
app.assertScreenshot(.sessionVerification, step: Step.waitingForOtherDevice)
|
||||
|
||||
XCTAssert(app.buttons["sasVerificationStartButton"].waitForExistence(timeout: 5.0))
|
||||
XCTAssert(app.buttons[A11yIdentifiers.sessionVerificationScreen.startSasVerification].waitForExistence(timeout: 5.0))
|
||||
app.assertScreenshot(.sessionVerification, step: Step.useEmojiComparisonPrompt)
|
||||
|
||||
app.buttons["sasVerificationStartButton"].tap()
|
||||
app.buttons[A11yIdentifiers.sessionVerificationScreen.startSasVerification].tap()
|
||||
app.assertScreenshot(.sessionVerification, step: Step.waitingForEmojis)
|
||||
|
||||
XCTAssert(app.buttons["challengeAcceptButton"].waitForExistence(timeout: 5.0))
|
||||
XCTAssert(app.buttons[A11yIdentifiers.sessionVerificationScreen.acceptChallenge].waitForExistence(timeout: 5.0))
|
||||
app.assertScreenshot(.sessionVerification, step: Step.compareEmojis)
|
||||
|
||||
app.buttons["challengeAcceptButton"].tap()
|
||||
app.buttons[A11yIdentifiers.sessionVerificationScreen.acceptChallenge].tap()
|
||||
app.assertScreenshot(.sessionVerification, step: Step.acceptingEmojis)
|
||||
|
||||
XCTAssert(app.staticTexts[ElementL10n.verificationConclusionOkSelfNoticeTitle].waitForExistence(timeout: 5.0))
|
||||
app.assertScreenshot(.sessionVerification, step: Step.verificationComplete)
|
||||
|
||||
app.buttons["closeButton"].tap()
|
||||
app.buttons[A11yIdentifiers.sessionVerificationScreen.close].tap()
|
||||
}
|
||||
|
||||
func testChallengeDoesNotMatch() {
|
||||
let app = Application.launch(.sessionVerification)
|
||||
app.assertScreenshot(.sessionVerification, step: Step.initialState)
|
||||
|
||||
app.buttons["requestVerificationButton"].tap()
|
||||
app.buttons[A11yIdentifiers.sessionVerificationScreen.requestVerification].tap()
|
||||
app.assertScreenshot(.sessionVerification, step: Step.waitingForOtherDevice)
|
||||
|
||||
XCTAssert(app.buttons["sasVerificationStartButton"].waitForExistence(timeout: 5.0))
|
||||
XCTAssert(app.buttons[A11yIdentifiers.sessionVerificationScreen.startSasVerification].waitForExistence(timeout: 5.0))
|
||||
app.assertScreenshot(.sessionVerification, step: Step.useEmojiComparisonPrompt)
|
||||
|
||||
app.buttons["sasVerificationStartButton"].tap()
|
||||
app.buttons[A11yIdentifiers.sessionVerificationScreen.startSasVerification].tap()
|
||||
app.assertScreenshot(.sessionVerification, step: Step.waitingForEmojis)
|
||||
|
||||
XCTAssert(app.buttons["challengeAcceptButton"].waitForExistence(timeout: 5.0))
|
||||
XCTAssert(app.buttons[A11yIdentifiers.sessionVerificationScreen.acceptChallenge].waitForExistence(timeout: 5.0))
|
||||
app.assertScreenshot(.sessionVerification, step: Step.compareEmojis)
|
||||
|
||||
app.buttons["challengeDeclineButton"].tap()
|
||||
app.buttons[A11yIdentifiers.sessionVerificationScreen.declineChallenge].tap()
|
||||
app.assertScreenshot(.sessionVerification, step: Step.verificationCancelled)
|
||||
|
||||
app.buttons["closeButton"].tap()
|
||||
app.buttons[A11yIdentifiers.sessionVerificationScreen.close].tap()
|
||||
}
|
||||
|
||||
func testSessionVerificationCancelation() {
|
||||
let app = Application.launch(.sessionVerification)
|
||||
app.assertScreenshot(.sessionVerification, step: Step.initialState)
|
||||
|
||||
app.buttons["requestVerificationButton"].tap()
|
||||
app.buttons[A11yIdentifiers.sessionVerificationScreen.requestVerification].tap()
|
||||
app.assertScreenshot(.sessionVerification, step: Step.waitingForOtherDevice)
|
||||
|
||||
XCTAssert(app.buttons["sasVerificationStartButton"].waitForExistence(timeout: 5.0))
|
||||
XCTAssert(app.buttons[A11yIdentifiers.sessionVerificationScreen.startSasVerification].waitForExistence(timeout: 5.0))
|
||||
app.assertScreenshot(.sessionVerification, step: Step.useEmojiComparisonPrompt)
|
||||
|
||||
app.buttons["sasVerificationStartButton"].tap()
|
||||
app.buttons[A11yIdentifiers.sessionVerificationScreen.startSasVerification].tap()
|
||||
app.assertScreenshot(.sessionVerification, step: Step.waitingForEmojis)
|
||||
|
||||
XCTAssert(app.buttons["challengeAcceptButton"].waitForExistence(timeout: 5.0))
|
||||
XCTAssert(app.buttons[A11yIdentifiers.sessionVerificationScreen.acceptChallenge].waitForExistence(timeout: 5.0))
|
||||
app.assertScreenshot(.sessionVerification, step: Step.compareEmojis)
|
||||
|
||||
app.buttons["closeButton"].tap()
|
||||
app.buttons[A11yIdentifiers.sessionVerificationScreen.close].tap()
|
||||
app.assertScreenshot(.sessionVerification, step: Step.verificationCancelled)
|
||||
|
||||
app.buttons["closeButton"].tap()
|
||||
app.buttons[A11yIdentifiers.sessionVerificationScreen.close].tap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,14 +29,14 @@ class SoftLogoutUITests: XCTestCase {
|
||||
func testInitialState() {
|
||||
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.")
|
||||
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.")
|
||||
XCTAssertTrue(app.staticTexts[A11yIdentifiers.softLogoutScreen.title].exists, "The title should be shown.")
|
||||
XCTAssertTrue(app.staticTexts[A11yIdentifiers.softLogoutScreen.message].exists, "The message 1 should be shown.")
|
||||
XCTAssertTrue(app.staticTexts[A11yIdentifiers.softLogoutScreen.clearDataTitle].exists, "The clear data title should be shown.")
|
||||
XCTAssertTrue(app.staticTexts[A11yIdentifiers.softLogoutScreen.clearDataMessage].exists, "The clear data message should be shown.")
|
||||
XCTAssertTrue(app.secureTextFields[A11yIdentifiers.softLogoutScreen.password].exists, "The password text field should be shown.")
|
||||
XCTAssertTrue(app.buttons[A11yIdentifiers.softLogoutScreen.next].exists, "The next button should be shown.")
|
||||
XCTAssertTrue(app.buttons[A11yIdentifiers.softLogoutScreen.forgotPassword].exists, "The forgot password button should be shown.")
|
||||
XCTAssertTrue(app.buttons[A11yIdentifiers.softLogoutScreen.clearData].exists, "The clear data button should be shown.")
|
||||
|
||||
app.assertScreenshot(.softLogout)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ class UserSessionScreenTests: XCTestCase {
|
||||
|
||||
app.assertScreenshot(.userSessionScreen, step: 1)
|
||||
|
||||
app.buttons["roomName:\(roomName)"].tap()
|
||||
app.buttons[A11yIdentifiers.homeScreen.roomName(roomName)].tap()
|
||||
|
||||
XCTAssert(app.staticTexts[roomName].waitForExistence(timeout: 5.0))
|
||||
|
||||
|
||||
@@ -63,5 +63,6 @@ targets:
|
||||
- path: ../../ElementX/Sources/Generated/Strings.swift
|
||||
- path: ../../ElementX/Sources/Generated/Strings+Untranslated.swift
|
||||
- path: ../../ElementX/Resources
|
||||
- path: ../../ElementX/Sources/Other/AccessibilityIdentifiers.swift
|
||||
- path: ../../ElementX/Sources/Other/Extensions/Bundle.swift
|
||||
- path: ../../ElementX/Sources/Other/Extensions/XCUIElement.swift
|
||||
|
||||
Reference in New Issue
Block a user