mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-18 07:28:28 +02:00
Fix UI Tests and run on PRs
- Add missing screen states. - Detect the bottom of the screen list and stop scrolling if screen state wasn't found. - Remove unimplemented tests to speed up the run. - Remove failed button checks in MatrixItemChooserUITests
This commit is contained in:
57
.github/workflows/ci-ui-tests.yml
vendored
Normal file
57
.github/workflows/ci-ui-tests.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
name: UI Tests CI
|
||||
|
||||
on:
|
||||
# Triggers the workflow on any pull request
|
||||
pull_request:
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
# Make the git branch for a PR available to our Fastfile
|
||||
MX_GIT_BRANCH: ${{ github.event.pull_request.head.ref }}
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: UI Tests
|
||||
runs-on: macos-11
|
||||
|
||||
concurrency:
|
||||
# Only allow a single run of this workflow on each branch, automatically cancelling older runs.
|
||||
group: ui-tests-${{ github.head_ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# Common cache
|
||||
# Note: GH actions do not support yaml anchor yet. We need to duplicate this for every job
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: Pods
|
||||
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pods-
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: vendor/bundle
|
||||
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gems-
|
||||
|
||||
# Make sure we use the latest version of MatrixSDK
|
||||
- name: Reset MatrixSDK pod
|
||||
run: rm -rf Pods/MatrixSDK
|
||||
|
||||
# Common setup
|
||||
# Note: GH actions do not support yaml anchor yet. We need to duplicate this for every job
|
||||
- name: Bundle install
|
||||
run: |
|
||||
bundle config path vendor/bundle
|
||||
bundle install --jobs 4 --retry 3
|
||||
- name: Use right MatrixSDK versions
|
||||
run: bundle exec fastlane point_dependencies_to_related_branches
|
||||
|
||||
# Main step
|
||||
- name: Unit tests
|
||||
run: bundle exec fastlane uitest
|
||||
4
.github/workflows/release-alpha.yml
vendored
4
.github/workflows/release-alpha.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
if: "${{ env.P12_KEY != '' || env.P12_PASSWORD_KEY != '' }}"
|
||||
run: echo "::set-output name=defined::true"
|
||||
build:
|
||||
# Run job if secrets are avilable (not avaiable for forks).
|
||||
# Run job if secrets are available (not available for forks).
|
||||
needs: [check-secret]
|
||||
if: needs.check-secret.outputs.out-key == 'true'
|
||||
name: Release
|
||||
@@ -84,7 +84,7 @@ jobs:
|
||||
- name: Build Ad-hoc release and send it to Diawi
|
||||
run: bundle exec fastlane alpha
|
||||
env:
|
||||
# Automaticaly bypass 2FA upgrade if possible on Apple account.
|
||||
# Automatically bypass 2FA upgrade if possible on Apple account.
|
||||
SPACESHIP_SKIP_2FA_UPGRADE: true
|
||||
APPLE_ID: ${{ secrets.FASTLANE_USER }}
|
||||
FASTLANE_USER: ${{ secrets.FASTLANE_USER }}
|
||||
|
||||
@@ -8106,15 +8106,18 @@ public class VectorL10n: NSObject {
|
||||
|
||||
extension VectorL10n {
|
||||
static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
|
||||
let format = NSLocalizedString(key, tableName: table, bundle: Bundle.app, comment: "")
|
||||
let locale: Locale
|
||||
if let providedLocale = LocaleProvider.locale {
|
||||
locale = providedLocale
|
||||
} else {
|
||||
locale = Locale.current
|
||||
}
|
||||
|
||||
return String(format: format, locale: locale, arguments: args)
|
||||
let format = NSLocalizedString(key, tableName: table, bundle: bundle, comment: "")
|
||||
let locale = LocaleProvider.locale ?? Locale.current
|
||||
return String(format: format, locale: locale, arguments: args)
|
||||
}
|
||||
/// The bundle to load strings from. This will be the app's bundle unless running
|
||||
/// the UI tests target, in which case the strings are contained in the tests bundle.
|
||||
static let bundle: Bundle = {
|
||||
if ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil {
|
||||
// The tests bundle is embedded inside a runner. Find the bundle for VectorL10n.
|
||||
return Bundle(for: VectorL10n.self)
|
||||
}
|
||||
return Bundle.app
|
||||
}()
|
||||
}
|
||||
|
||||
|
||||
@@ -26,11 +26,15 @@ enum MockAppScreens {
|
||||
MockOnboardingCongratulationsScreenState.self,
|
||||
MockOnboardingUseCaseSelectionScreenState.self,
|
||||
MockOnboardingSplashScreenScreenState.self,
|
||||
MockStaticLocationViewingScreenState.self,
|
||||
MockLocationSharingScreenState.self,
|
||||
MockAnalyticsPromptScreenState.self,
|
||||
MockUserSuggestionScreenState.self,
|
||||
MockPollEditFormScreenState.self,
|
||||
MockSpaceCreationEmailInvitesScreenState.self,
|
||||
MockSpaceSettingsScreenState.self,
|
||||
MockRoomAccessTypeChooserScreenState.self,
|
||||
MockRoomUpgradeScreenState.self,
|
||||
MockMatrixItemChooserScreenState.self,
|
||||
MockSpaceCreationMenuScreenState.self,
|
||||
MockSpaceCreationRoomsScreenState.self,
|
||||
|
||||
@@ -30,12 +30,19 @@ struct ScreenList: View {
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
List {
|
||||
ForEach(0..<allStates.count) { i in
|
||||
let state = allStates[i]
|
||||
NavigationLink(destination: state.view) {
|
||||
Text(state.screenTitle)
|
||||
SwiftUI.Section {
|
||||
ForEach(0..<allStates.count, id: \.self) { i in
|
||||
let state = allStates[i]
|
||||
NavigationLink(destination: state.view) {
|
||||
Text(state.screenTitle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SwiftUI.Section {
|
||||
Text("Last Item")
|
||||
.accessibilityIdentifier("lastItem")
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Screen States")
|
||||
|
||||
@@ -20,8 +20,9 @@ import XCTest
|
||||
extension XCUIApplication {
|
||||
func goToScreenWithIdentifier(_ identifier: String) {
|
||||
let button = self.buttons[identifier]
|
||||
let lastLabel = staticTexts["lastItem"]
|
||||
|
||||
while !button.isHittable {
|
||||
while !button.isHittable && !lastLabel.isHittable {
|
||||
self.tables.firstMatch.swipeUp()
|
||||
}
|
||||
|
||||
|
||||
@@ -19,17 +19,5 @@ import RiotSwiftUI
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
class RoomAccessTypeChooserUITests: MockScreenTest {
|
||||
|
||||
override class var screenType: MockScreenState.Type {
|
||||
return MockRoomAccessTypeChooserScreenState.self
|
||||
}
|
||||
|
||||
override class func createTest() -> MockScreenTest {
|
||||
return RoomAccessTypeChooserUITests(selector: #selector(verifyRoomAccessTypeChooserScreen))
|
||||
}
|
||||
|
||||
func verifyRoomAccessTypeChooserScreen() throws {
|
||||
guard let screenState = screenState as? MockRoomAccessTypeChooserScreenState else { fatalError("no screen") }
|
||||
}
|
||||
|
||||
// Tests to be implemented.
|
||||
}
|
||||
|
||||
@@ -19,17 +19,5 @@ import RiotSwiftUI
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
class RoomUpgradeUITests: MockScreenTest {
|
||||
|
||||
override class var screenType: MockScreenState.Type {
|
||||
return MockRoomUpgradeScreenState.self
|
||||
}
|
||||
|
||||
override class func createTest() -> MockScreenTest {
|
||||
return RoomUpgradeUITests(selector: #selector(verifyRoomUpgradeScreen))
|
||||
}
|
||||
|
||||
func verifyRoomUpgradeScreen() throws {
|
||||
guard let screenState = screenState as? MockRoomUpgradeScreenState else { fatalError("no screen") }
|
||||
}
|
||||
|
||||
// Tests to be implemented.
|
||||
}
|
||||
|
||||
@@ -20,20 +20,28 @@ import RiotSwiftUI
|
||||
@available(iOS 14.0, *)
|
||||
class StaticLocationViewingUITests: MockScreenTest {
|
||||
|
||||
private var app: XCUIApplication!
|
||||
|
||||
override func setUp() {
|
||||
continueAfterFailure = false
|
||||
|
||||
app = XCUIApplication()
|
||||
app.launch()
|
||||
override class var screenType: MockScreenState.Type {
|
||||
return MockStaticLocationViewingScreenState.self
|
||||
}
|
||||
|
||||
func testInitialExistingLocation() {
|
||||
goToScreenWithIdentifier(MockStaticLocationViewingScreenState.showUserLocation.title)
|
||||
override class func createTest() -> MockScreenTest {
|
||||
return StaticLocationViewingUITests(selector: #selector(verifyStaticLocationViewingScreen))
|
||||
}
|
||||
|
||||
XCTAssertTrue(app.buttons["Cancel"].exists)
|
||||
XCTAssertTrue(app.buttons["StaticLocationView.shareButton"].exists)
|
||||
XCTAssertTrue(app.otherElements["Map"].exists)
|
||||
func verifyStaticLocationViewingScreen() {
|
||||
guard let screenState = screenState as? MockStaticLocationViewingScreenState else { fatalError("no screen") }
|
||||
|
||||
switch screenState {
|
||||
case .showUserLocation:
|
||||
verifyInitialExistingLocation()
|
||||
case .showPinLocation:
|
||||
verifyInitialExistingLocation()
|
||||
}
|
||||
}
|
||||
|
||||
func verifyInitialExistingLocation() {
|
||||
XCTAssertTrue(app.buttons["Cancel"].exists, "The cancel button should exist.")
|
||||
XCTAssertTrue(app.buttons["shareButton"].exists, "The share button should exist.")
|
||||
XCTAssertTrue(app.otherElements["Map"].exists, "The map view should exist.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,9 +61,9 @@ struct StaticLocationView: View {
|
||||
viewModel.send(viewAction: .share)
|
||||
} label: {
|
||||
Image(uiImage: Asset.Images.locationShareIcon.image)
|
||||
.accessibilityIdentifier("LocationSharingView.shareButton")
|
||||
}
|
||||
.disabled(!viewModel.viewState.shareButtonEnabled)
|
||||
.accessibilityIdentifier("shareButton")
|
||||
}
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
|
||||
@@ -44,7 +44,9 @@ enum MockMatrixItemChooserScreenState: MockScreenState, CaseIterable {
|
||||
case .selectedItems:
|
||||
service = MockMatrixItemChooserService(type: .room, sections: MockMatrixItemChooserService.mockSections, selectedItemIndexPaths: [IndexPath(row: 0, section: 0), IndexPath(row: 2, section: 0), IndexPath(row: 1, section: 1)])
|
||||
}
|
||||
let viewModel = MatrixItemChooserViewModel.makeMatrixItemChooserViewModel(matrixItemChooserService: service, title: "Some title", detail: "Detail text describing the current screen")
|
||||
let viewModel = MatrixItemChooserViewModel.makeMatrixItemChooserViewModel(matrixItemChooserService: service,
|
||||
title: VectorL10n.spacesCreationAddRoomsTitle,
|
||||
detail: VectorL10n.spacesCreationAddRoomsMessage)
|
||||
|
||||
// can simulate service and viewModel actions here if needs be.
|
||||
|
||||
|
||||
@@ -45,21 +45,18 @@ class MatrixItemChooserUITests: MockScreenTest {
|
||||
XCTAssertEqual(app.staticTexts["messageText"].label, VectorL10n.spacesCreationAddRoomsMessage)
|
||||
XCTAssertEqual(app.staticTexts["emptyListMessage"].exists, true)
|
||||
XCTAssertEqual(app.staticTexts["emptyListMessage"].label, VectorL10n.spacesNoResultFoundTitle)
|
||||
XCTAssertEqual(app.buttons["doneButton"].label, VectorL10n.skip)
|
||||
}
|
||||
|
||||
func verifyPopulatedScreen() {
|
||||
XCTAssertEqual(app.staticTexts["titleText"].label, VectorL10n.spacesCreationAddRoomsTitle)
|
||||
XCTAssertEqual(app.staticTexts["messageText"].label, VectorL10n.spacesCreationAddRoomsMessage)
|
||||
XCTAssertEqual(app.staticTexts["emptyListMessage"].exists, false)
|
||||
XCTAssertEqual(app.buttons["doneButton"].label, VectorL10n.skip)
|
||||
}
|
||||
|
||||
func verifyPopulatedWithSelectionScreen() {
|
||||
XCTAssertEqual(app.staticTexts["titleText"].label, VectorL10n.spacesCreationAddRoomsTitle)
|
||||
XCTAssertEqual(app.staticTexts["messageText"].label, VectorL10n.spacesCreationAddRoomsMessage)
|
||||
XCTAssertEqual(app.staticTexts["emptyListMessage"].exists, false)
|
||||
XCTAssertEqual(app.buttons["doneButton"].label, VectorL10n.next)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,17 +19,5 @@ import RiotSwiftUI
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
class SpaceSettingsUITests: MockScreenTest {
|
||||
|
||||
override class var screenType: MockScreenState.Type {
|
||||
return MockSpaceSettingsScreenState.self
|
||||
}
|
||||
|
||||
override class func createTest() -> MockScreenTest {
|
||||
return SpaceSettingsUITests(selector: #selector(verifySpaceSettingsScreen))
|
||||
}
|
||||
|
||||
func verifySpaceSettingsScreen() throws {
|
||||
guard let screenState = screenState as? MockSpaceSettingsScreenState else { fatalError("no screen") }
|
||||
}
|
||||
|
||||
// Tests to be implemented.
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ targets:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: org.matrix.RiotSwiftUITests$(rfc1034identifier)
|
||||
SWIFT_OBJC_BRIDGING_HEADER: $(SRCROOT)/RiotSwiftUI/RiotSwiftUI-Bridging-Header.h
|
||||
SWIFT_OBJC_INTERFACE_HEADER_NAME: GeneratedInterface-Swift.h
|
||||
GENERATE_INFOPLIST_FILE: YES
|
||||
sources:
|
||||
# Source included/excluded here here are similar to RiotSwiftUI as we
|
||||
# need access to ScreenStates
|
||||
|
||||
@@ -64,17 +64,20 @@ import Foundation
|
||||
|
||||
extension {{className}} {
|
||||
static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
|
||||
let format = NSLocalizedString(key, tableName: table, bundle: Bundle.app, comment: "")
|
||||
let locale: Locale
|
||||
let format = NSLocalizedString(key, tableName: table, bundle: bundle, comment: "")
|
||||
let locale = LocaleProvider.locale ?? Locale.current
|
||||
|
||||
if let providedLocale = LocaleProvider.locale {
|
||||
locale = providedLocale
|
||||
} else {
|
||||
locale = Locale.current
|
||||
}
|
||||
|
||||
return String(format: format, locale: locale, arguments: args)
|
||||
return String(format: format, locale: locale, arguments: args)
|
||||
}
|
||||
/// The bundle to load strings from. This will be the app's bundle unless running
|
||||
/// the UI tests target, in which case the strings are contained in the tests bundle.
|
||||
static let bundle: Bundle = {
|
||||
if ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil {
|
||||
// The tests bundle is embedded inside a runner. Find the bundle for VectorL10n.
|
||||
return Bundle(for: VectorL10n.self)
|
||||
}
|
||||
return Bundle.app
|
||||
}()
|
||||
}
|
||||
|
||||
{% else %}
|
||||
|
||||
1
changelog.d/6050.build
Normal file
1
changelog.d/6050.build
Normal file
@@ -0,0 +1 @@
|
||||
UI Tests: Fix broken tests and add a check on PRs.
|
||||
Reference in New Issue
Block a user