Fix UI Tests for OnboardingScreen, BugReportScreen, ServerSelectionScreen, and UserSessionFlows. (#549)

* Fix OnboardingScreen UI Tests

Disable the swipe tests for now as there is only a single page.

* Fix BugReportScreen UI Tests.

Use snapshots more and remove manual validation method.

* Fix ServerSelectionScreen UI Tests.

* Fix SessionVerificationScreen UI Tests.

* Fix UserSessionFlows UI Tests
This commit is contained in:
Doug 2023-02-08 14:11:09 +00:00 committed by GitHub
parent 588975d53f
commit 22a99482a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
100 changed files with 286 additions and 226 deletions

View File

@ -34,31 +34,10 @@ enum OnboardingViewModelAction {
}
struct OnboardingViewState: BindableState {
/// The colours of the background gradient shown behind the 4 pages.
private let gradientColors = [
Color(red: 0.95, green: 0.98, blue: 0.96),
Color(red: 0.89, green: 0.96, blue: 0.97),
Color(red: 0.95, green: 0.89, blue: 0.97),
Color(red: 0.81, green: 0.95, blue: 0.91),
Color(red: 0.95, green: 0.98, blue: 0.96)
]
/// An array containing all content of the carousel pages
let content: [OnboardingPageContent]
var bindings: OnboardingBindings
/// The background gradient for all 4 pages and the hidden page at the start of the carousel.
var backgroundGradient: Gradient {
if Tests.isRunningUITests {
return Gradient(colors: [.white])
}
// Include the extra stop for the hidden page at the start of the carousel.
// (The last color is the right-hand stop, but we need the left-hand stop,
// so take the last but one color from the array).
let hiddenPageColor = gradientColors[gradientColors.count - 2]
return Gradient(colors: [hiddenPageColor] + gradientColors)
}
init() {
content = [
OnboardingPageContent(title: ElementL10n.ftueAuthCarouselWelcomeTitle.tinting(".", color: .element.accent),

View File

@ -21,6 +21,8 @@ import SwiftUI
struct OnboardingBackgroundView: View {
@Environment(\.colorScheme) private var colorScheme
var isAnimated = true
@State private var factor = 0.0
@State private var isReversed = false
@ -39,6 +41,8 @@ struct OnboardingBackgroundView: View {
}
.frame(width: geometry.size.width, height: geometry.size.height)
.onReceive(timer) { _ in
guard isAnimated else { return }
if isReversed {
guard factor > 0 else {
isReversed = false

View File

@ -19,7 +19,6 @@ import SwiftUI
/// The screen shown at the beginning of the onboarding flow.
struct OnboardingScreen: View {
@Environment(\.colorScheme) private var colorScheme
@Environment(\.layoutDirection) private var layoutDirection
@Environment(\.verticalSizeClass) private var verticalSizeClass
@ -35,7 +34,8 @@ struct OnboardingScreen: View {
var body: some View {
ZStack {
OnboardingBackgroundView()
OnboardingBackgroundView(isAnimated: !Tests.isRunningUITests)
GeometryReader { geometry in
ZStack {
VStack(alignment: .leading) {
@ -99,19 +99,6 @@ struct OnboardingScreen: View {
.readableFrame()
}
@ViewBuilder
/// The view's background, showing a gradient in light mode and a solid colour in dark mode.
var background: some View {
if colorScheme == .light {
LinearGradient(gradient: context.viewState.backgroundGradient,
startPoint: .leading,
endPoint: .trailing)
.flipsForRightToLeftLayoutDirection(true)
} else {
Color.element.background
}
}
// MARK: - Animation
/// Starts the animation timer for an automatic carousel effect.

View File

@ -21,13 +21,9 @@ class BugReportUITests: XCTestCase {
func testInitialStateComponents() {
let app = Application.launch()
app.goToScreenWithIdentifier(.bugReport)
verifyInitialStateComponents(in: app)
XCTAssertFalse(app.images["screenshotImage"].exists)
XCTAssertFalse(app.buttons["removeScreenshotButton"].exists)
app.assertScreenshot(.bugReport)
// Initial state without a screenshot attached.
app.assertScreenshot(.bugReport, step: 0)
}
func testToggleSendingLogs() {
@ -39,53 +35,34 @@ class BugReportUITests: XCTestCase {
let sendingLogsToggle = app.switches["sendLogsToggle"]
XCTAssert(sendingLogsToggle.exists)
XCTAssertFalse(sendingLogsToggle.isOn)
app.assertScreenshot(.bugReport, step: 1)
}
func testReportText() {
let app = Application.launch()
app.goToScreenWithIdentifier(.bugReport)
// type 4 chars
// Type 4 characters and the send button should be disabled.
app.textViews["reportTextView"].clearAndTypeText("Text")
XCTAssertFalse(app.buttons["sendButton"].isEnabled)
app.assertScreenshot(.bugReport, step: 2)
// type one more char and see the button enabled
// Type more than 4 characters and send the button should become enabled.
app.textViews["reportTextView"].clearAndTypeText("Longer text")
XCTAssert(app.buttons["sendButton"].isEnabled)
app.assertScreenshot(.bugReport, step: 3)
}
func testInitialStateComponentsWithScreenshot() {
let app = Application.launch()
app.goToScreenWithIdentifier(.bugReportWithScreenshot)
verifyInitialStateComponents(in: app)
// Initial state with a screenshot attached.
XCTAssert(app.images["screenshotImage"].exists)
XCTAssert(app.buttons["removeScreenshotButton"].exists)
app.assertScreenshot(.bugReportWithScreenshot)
}
func verifyInitialStateComponents(in app: XCUIApplication) {
XCTAssert(app.navigationBars[ElementL10n.titleActivityBugReport].exists)
let descLabel = app.staticTexts["reportBugDescription"]
XCTAssert(descLabel.exists)
XCTAssertEqual(descLabel.label, ElementL10n.sendBugReportDescription)
let sendLogsDescLabel = app.staticTexts["sendLogsDescription"]
XCTAssert(sendLogsDescLabel.exists)
XCTAssertEqual(sendLogsDescLabel.label, ElementL10n.sendBugReportLogsDescription)
XCTAssert(app.textViews["reportTextView"].exists)
let sendLogsToggle = app.switches["sendLogsToggle"]
XCTAssert(sendLogsToggle.exists)
XCTAssert(sendLogsToggle.isOn)
let sendLogsLabel = app.staticTexts["sendLogsText"]
XCTAssert(sendLogsLabel.exists)
XCTAssertEqual(sendLogsLabel.label, ElementL10n.sendBugReportIncludeLogs)
let sendButton = app.buttons["sendButton"]
XCTAssert(sendButton.exists)
XCTAssertEqual(sendButton.label, ElementL10n.actionSend)
XCTAssertFalse(sendButton.isEnabled)
}
}
extension XCUIElement {

View File

@ -21,15 +21,11 @@ class OnboardingUITests: XCTestCase {
func testInitialStateComponents() {
let app = Application.launch()
app.goToScreenWithIdentifier(.onboarding)
let getStartedButton = app.buttons["getStartedButton"]
XCTAssertTrue(getStartedButton.exists, "The primary action button should be shown.")
XCTAssertEqual(getStartedButton.label, ElementL10n.loginSplashSubmit)
app.assertScreenshot(.onboarding)
}
func testSwipingBetweenPages() {
// This test has been disabled for now as there is only a single page.
func disabled_testSwipingBetweenPages() {
let app = Application.launch()
app.goToScreenWithIdentifier(.onboarding)

View File

@ -26,21 +26,10 @@ class ServerSelectionUITests: XCTestCase {
let app = Application.launch()
app.goToScreenWithIdentifier(.serverSelection)
// Then it should be configured for matrix.org and with a cancel button
let serverTextField = app.textFields[textFieldIdentifier]
XCTAssertEqual(serverTextField.value as? String, "matrix.org", "The server shown should be matrix.org with the https scheme hidden.")
let confirmButton = app.buttons["confirmButton"]
XCTAssertEqual(confirmButton.label, ElementL10n.actionConfirm, "The confirm button should say Confirm when in modal presentation.")
XCTAssertTrue(confirmButton.exists, "The confirm button should always be shown.")
XCTAssertTrue(confirmButton.isEnabled, "The confirm button should be enabled when there is an address.")
XCTAssertTrue(app.staticTexts[ElementL10n.serverSelectionServerFooter].exists)
let dismissButton = app.buttons["dismissButton"]
XCTAssertTrue(dismissButton.exists, "The dismiss button should be shown during modal presentation.")
app.assertScreenshot(.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.")
}
func testEmptyAddress() async {
@ -53,11 +42,9 @@ class ServerSelectionUITests: XCTestCase {
app.textFields[textFieldIdentifier].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.")
let confirmButton = app.buttons["confirmButton"]
XCTAssertTrue(confirmButton.exists, "The confirm button should always be shown.")
XCTAssertFalse(confirmButton.isEnabled, "The confirm button should be disabled when the address is empty.")
XCTAssertFalse(app.buttons["confirmButton"].isEnabled, "The confirm button should be disabled when the address is empty.")
}
func testInvalidAddress() {
@ -69,13 +56,9 @@ class ServerSelectionUITests: XCTestCase {
app.textFields[textFieldIdentifier].clearAndTypeText("thisisbad\n") // The tests only accept an address from LoginHomeserver.mockXYZ
// Then an error should be shown and the confirmation button disabled.
XCTAssertEqual(app.textFields[textFieldIdentifier].value as? String, "thisisbad", "The text field should show the entered server.")
let confirmButton = app.buttons["confirmButton"]
XCTAssertTrue(confirmButton.exists, "The confirm button should always be shown.")
XCTAssertFalse(confirmButton.isEnabled, "The confirm button should be disabled when there is an error.")
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.")
}
func testNonModalPresentation() {
@ -84,12 +67,8 @@ class ServerSelectionUITests: XCTestCase {
app.goToScreenWithIdentifier(.serverSelectionNonModal)
// Then the screen should be tweaked slightly to reflect the change of navigation.
let dismissButton = app.buttons["dismissButton"]
XCTAssertFalse(dismissButton.exists, "The dismiss button should be hidden when not in modal presentation.")
let confirmButton = app.buttons["confirmButton"]
XCTAssertEqual(confirmButton.label, ElementL10n.actionNext, "The confirm button should say Next when not in modal presentation.")
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.")
}
}

View File

@ -18,94 +18,87 @@ import ElementX
import XCTest
class SessionVerificationUITests: XCTestCase {
enum Step {
static let initialState = 0
static let waitingForOtherDevice = 1
static let useEmojiComparisonPrompt = 2
static let waitingForEmojis = 3
static let compareEmojis = 4
static let acceptingEmojis = 5
static let verificationComplete = 6
static let verificationCancelled = 7
}
func testChallengeMatches() {
let app = Application.launch()
app.goToScreenWithIdentifier(.sessionVerification)
XCTAssert(app.buttons["requestVerificationButton"].exists)
XCTAssert(app.buttons["closeButton"].exists)
XCTAssert(app.staticTexts["titleLabel"].exists)
app.assertScreenshot(.sessionVerification)
app.assertScreenshot(.sessionVerification, step: Step.initialState)
app.buttons["requestVerificationButton"].tap()
XCTAssert(app.activityIndicators["requestingVerificationProgressView"].exists)
app.assertScreenshot(.sessionVerification, step: Step.waitingForOtherDevice)
XCTAssert(app.buttons["sasVerificationStartButton"].waitForExistence(timeout: 5.0))
app.buttons["sasVerificationStartButton"].tap()
app.assertScreenshot(.sessionVerification, step: Step.useEmojiComparisonPrompt)
XCTAssert(app.activityIndicators["startingSasVerification"].waitForExistence(timeout: 5.0))
XCTAssert(app.activityIndicators["startedSasVerification"].waitForExistence(timeout: 5.0))
app.buttons["sasVerificationStartButton"].tap()
app.assertScreenshot(.sessionVerification, step: Step.waitingForEmojis)
XCTAssert(app.buttons["challengeAcceptButton"].waitForExistence(timeout: 5.0))
XCTAssert(app.buttons["challengeDeclineButton"].waitForExistence(timeout: 5.0))
app.assertScreenshot(.sessionVerification, step: Step.compareEmojis)
app.buttons["challengeAcceptButton"].tap()
XCTAssert(app.activityIndicators["acceptingChallengeProgressView"].exists)
app.assertScreenshot(.sessionVerification, step: Step.acceptingEmojis)
XCTAssert(app.images["sessionVerificationSucceededIcon"].waitForExistence(timeout: 5.0))
XCTAssert(app.staticTexts[ElementL10n.verificationConclusionOkSelfNoticeTitle].waitForExistence(timeout: 5.0))
app.assertScreenshot(.sessionVerification, step: Step.verificationComplete)
XCTAssert(app.buttons["finishButton"].exists)
XCTAssert(app.buttons["closeButton"].exists)
app.buttons["closeButton"].tap()
}
func testChallengeDoesNotMatch() {
let app = Application.launch()
app.goToScreenWithIdentifier(.sessionVerification)
XCTAssert(app.buttons["requestVerificationButton"].exists)
XCTAssert(app.buttons["closeButton"].exists)
XCTAssert(app.staticTexts["titleLabel"].exists)
app.assertScreenshot(.sessionVerification, step: Step.initialState)
app.buttons["requestVerificationButton"].tap()
XCTAssert(app.activityIndicators["requestingVerificationProgressView"].exists)
app.assertScreenshot(.sessionVerification, step: Step.waitingForOtherDevice)
XCTAssert(app.buttons["sasVerificationStartButton"].waitForExistence(timeout: 5.0))
app.buttons["sasVerificationStartButton"].tap()
app.assertScreenshot(.sessionVerification, step: Step.useEmojiComparisonPrompt)
XCTAssert(app.activityIndicators["startingSasVerification"].waitForExistence(timeout: 5.0))
XCTAssert(app.activityIndicators["startedSasVerification"].waitForExistence(timeout: 5.0))
app.buttons["sasVerificationStartButton"].tap()
app.assertScreenshot(.sessionVerification, step: Step.waitingForEmojis)
XCTAssert(app.buttons["challengeAcceptButton"].waitForExistence(timeout: 5.0))
XCTAssert(app.buttons["challengeDeclineButton"].waitForExistence(timeout: 5.0))
app.assertScreenshot(.sessionVerification, step: Step.compareEmojis)
app.buttons["challengeDeclineButton"].tap()
XCTAssert(app.images["sessionVerificationFailedIcon"].exists)
XCTAssert(app.buttons["restartButton"].exists)
app.assertScreenshot(.sessionVerification, step: Step.verificationCancelled)
XCTAssert(app.buttons["closeButton"].exists)
app.buttons["closeButton"].tap()
}
func testSessionVerificationCancelation() {
let app = Application.launch()
app.goToScreenWithIdentifier(.sessionVerification)
XCTAssert(app.buttons["requestVerificationButton"].exists)
XCTAssert(app.buttons["closeButton"].exists)
XCTAssert(app.staticTexts["titleLabel"].exists)
app.assertScreenshot(.sessionVerification, step: Step.initialState)
app.buttons["requestVerificationButton"].tap()
XCTAssert(app.activityIndicators["requestingVerificationProgressView"].waitForExistence(timeout: 1))
app.assertScreenshot(.sessionVerification, step: Step.waitingForOtherDevice)
XCTAssert(app.buttons["sasVerificationStartButton"].waitForExistence(timeout: 5.0))
app.buttons["sasVerificationStartButton"].tap()
app.assertScreenshot(.sessionVerification, step: Step.useEmojiComparisonPrompt)
XCTAssert(app.activityIndicators["startingSasVerification"].waitForExistence(timeout: 5.0))
XCTAssert(app.activityIndicators["startedSasVerification"].waitForExistence(timeout: 5.0))
app.buttons["sasVerificationStartButton"].tap()
app.assertScreenshot(.sessionVerification, step: Step.waitingForEmojis)
XCTAssert(app.buttons["challengeAcceptButton"].waitForExistence(timeout: 5.0))
app.assertScreenshot(.sessionVerification, step: Step.compareEmojis)
app.buttons["closeButton"].tap()
app.assertScreenshot(.sessionVerification, step: Step.verificationCancelled)
XCTAssert(app.images["sessionVerificationFailedIcon"].waitForExistence(timeout: 1))
XCTAssert(app.buttons["restartButton"].exists)
XCTAssert(app.buttons["closeButton"].exists)
app.buttons["closeButton"].tap()
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
changelog.d/534.bugfix Normal file
View File

@ -0,0 +1 @@
Fix UI Tests for OnboardingScreen, BugReportScreen, ServerSelectionScreen, and UserSessionFlows.