From a5562c02707c3ec629febebd495645e81ae480ad Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Mon, 28 Aug 2023 10:41:58 +0300 Subject: [PATCH] Check more screens in the integration tests. Refactor flows --- .../Other/AccessibilityIdentifiers.swift | 19 +++ .../View/RoomAttachmentPicker.swift | 4 + .../Screens/HomeScreen/View/HomeScreen.swift | 2 + .../View/HomeScreenUserMenuButton.swift | 1 + .../View/InviteUsersScreen.swift | 1 + .../SettingsScreen/View/SettingsScreen.swift | 13 +- .../View/StartChatScreen.swift | 1 + IntegrationTests/Sources/Common.swift | 2 +- IntegrationTests/Sources/UserFlowTests.swift | 137 +++++++++++++++--- 9 files changed, 152 insertions(+), 28 deletions(-) diff --git a/ElementX/Sources/Other/AccessibilityIdentifiers.swift b/ElementX/Sources/Other/AccessibilityIdentifiers.swift index 405929534..68c8ea061 100644 --- a/ElementX/Sources/Other/AccessibilityIdentifiers.swift +++ b/ElementX/Sources/Other/AccessibilityIdentifiers.swift @@ -35,6 +35,7 @@ struct A11yIdentifiers { static let roomMemberDetailsScreen = RoomMemberDetailsScreen() static let createRoomScreen = CreateRoomScreen() static let invitesScreen = InvitesScreen() + static let inviteUsersScreen = InviteUsersScreen() static let welcomeScreen = WelcomeScreen() static let migrationScreen = MigrationScreen() static let notificationSettingsScreen = NotificationSettingsScreen() @@ -66,6 +67,8 @@ struct A11yIdentifiers { let settings = "home_screen-settings" let signOut = "home_screen-sign_out" let verificationBannerContinue = "home_screen-verification_continue" + let invites = "home_screen-invites" + let startChat = "home_screen-start_chat" let roomNamePrefix = "home_screen-room_name" func roomName(_ name: String) -> String { @@ -79,6 +82,10 @@ struct A11yIdentifiers { let decline = "invites-decline" } + struct InviteUsersScreen { + let proceed = "invite_users-proceed" + } + struct LoginScreen { let emailUsername = "login-email_username" let password = "login-password" @@ -99,6 +106,10 @@ struct A11yIdentifiers { let name = "room-name" let avatar = "room-avatar" let attachmentPicker = "room-attachment_picker" + let attachmentPickerPhotoLibrary = "room-attachment_picker_photo_library" + let attachmentPickerDocuments = "room-attachment_picker_documents" + let attachmentPickerCamera = "room-attachment_picker_camera" + let attachmentPickerLocation = "room-attachment_picker_location" let timelineItemActionMenu = "room-timeline_item_action_menu" } @@ -136,6 +147,13 @@ struct A11yIdentifiers { } struct SettingsScreen { + let done = "settings-done" + let account = "settings-account" + let notifications = "settings-notifications" + let analytics = "settings-analytics" + let reportBug = "settings-report_bug" + let about = "settings_about" + let developerOptions = "settings_developer-options" let logout = "settings-logout" } @@ -153,6 +171,7 @@ struct A11yIdentifiers { struct StartChatScreen { let closeStartChat = "start_chat-close" + let createRoom = "start_chat-create_room" let inviteFriends = "start_chat-invite_friends" let searchNoResults = "start_chat-search_no_results" } diff --git a/ElementX/Sources/Screens/ComposerToolbar/View/RoomAttachmentPicker.swift b/ElementX/Sources/Screens/ComposerToolbar/View/RoomAttachmentPicker.swift index 521426c80..edfd86e32 100644 --- a/ElementX/Sources/Screens/ComposerToolbar/View/RoomAttachmentPicker.swift +++ b/ElementX/Sources/Screens/ComposerToolbar/View/RoomAttachmentPicker.swift @@ -39,6 +39,7 @@ struct RoomAttachmentPicker: View { } label: { PickerLabel(title: L10n.screenRoomAttachmentSourceGallery, icon: Image(systemName: "photo.fill")) } + .accessibilityLabel(A11yIdentifiers.roomScreen.attachmentPickerPhotoLibrary) Button { context.showAttachmentPopover = false @@ -46,6 +47,7 @@ struct RoomAttachmentPicker: View { } label: { PickerLabel(title: L10n.screenRoomAttachmentSourceFiles, icon: Image(systemName: "paperclip")) } + .accessibilityLabel(A11yIdentifiers.roomScreen.attachmentPickerDocuments) Button { context.showAttachmentPopover = false @@ -53,6 +55,7 @@ struct RoomAttachmentPicker: View { } label: { PickerLabel(title: L10n.screenRoomAttachmentSourceCamera, icon: Image(systemName: "camera.fill")) } + .accessibilityLabel(A11yIdentifiers.roomScreen.attachmentPickerCamera) Button { context.showAttachmentPopover = false @@ -60,6 +63,7 @@ struct RoomAttachmentPicker: View { } label: { PickerLabel(title: L10n.screenRoomAttachmentSourceLocation, icon: Image(asset: Asset.Images.locationPin)) } + .accessibilityLabel(A11yIdentifiers.roomScreen.attachmentPickerLocation) } .padding(.top, isPresented ? 20 : 0) .background { diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift index 98a1f0a40..a711eacc9 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift @@ -119,6 +119,7 @@ struct HomeScreen: View { HomeScreenInvitesButton(title: L10n.actionInvitesList, hasBadge: context.viewState.hasUnreadPendingInvitations) { context.send(viewAction: .selectInvites) } + .accessibilityLabel(A11yIdentifiers.homeScreen.invites) .frame(maxWidth: .infinity, alignment: .trailing) .padding(.vertical, -8.0) } @@ -178,6 +179,7 @@ struct HomeScreen: View { } label: { Image(systemName: "square.and.pencil") } + .accessibilityLabel(A11yIdentifiers.homeScreen.startChat) } /// Often times the scroll view's content size isn't correct yet when this method is called e.g. when cancelling a search diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenUserMenuButton.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenUserMenuButton.swift index 063296cc5..a06787ede 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenUserMenuButton.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenUserMenuButton.swift @@ -29,6 +29,7 @@ struct HomeScreenUserMenuButton: View { } label: { Label(L10n.commonSettings, systemImage: "gearshape") } + .accessibilityLabel(A11yIdentifiers.homeScreen.settings) } Section { MatrixUserShareLink(userID: context.viewState.userID) { diff --git a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift index ea640dbe8..59fb2a99a 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift @@ -130,6 +130,7 @@ struct InviteUsersScreen: View { Button(context.viewState.actionText) { context.send(viewAction: .proceed) } + .accessibilityIdentifier(A11yIdentifiers.inviteUsersScreen.proceed) .disabled(context.viewState.isActionDisabled) } } diff --git a/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift b/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift index f0a810a86..5fbf3006f 100644 --- a/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift +++ b/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift @@ -97,7 +97,7 @@ struct SettingsScreen: View { kind: .navigationLink { context.send(viewAction: .developerOptions) }) - .accessibilityIdentifier("developerOptionsButton") + .accessibilityLabel(A11yIdentifiers.settingsScreen.developerOptions) } } @@ -110,7 +110,7 @@ struct SettingsScreen: View { kind: .button { context.send(viewAction: .account) }) - .accessibilityIdentifier("notificationsButton") + .accessibilityLabel(A11yIdentifiers.settingsScreen.account) } // Message layout @@ -130,7 +130,7 @@ struct SettingsScreen: View { kind: .navigationLink { context.send(viewAction: .notifications) }) - .accessibilityIdentifier("notificationsButton") + .accessibilityLabel(A11yIdentifiers.settingsScreen.notifications) } // Analytics @@ -139,7 +139,7 @@ struct SettingsScreen: View { kind: .navigationLink { context.send(viewAction: .analytics) }) - .accessibilityIdentifier("analyticsButton") + .accessibilityLabel(A11yIdentifiers.settingsScreen.analytics) // Report Bug ListRow(label: .default(title: L10n.commonReportABug, @@ -147,7 +147,7 @@ struct SettingsScreen: View { kind: .navigationLink { context.send(viewAction: .reportBug) }) - .accessibilityIdentifier("reportBugButton") + .accessibilityIdentifier(A11yIdentifiers.settingsScreen.reportBug) // About ListRow(label: .default(title: L10n.commonAbout, @@ -155,7 +155,7 @@ struct SettingsScreen: View { kind: .navigationLink { context.send(viewAction: .about) }) - .accessibilityIdentifier("aboutButton") + .accessibilityIdentifier(A11yIdentifiers.settingsScreen.about) } } @@ -191,6 +191,7 @@ struct SettingsScreen: View { private var doneButton: some View { Button(L10n.actionDone, action: close) + .accessibilityLabel(A11yIdentifiers.settingsScreen.done) } private func close() { diff --git a/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift b/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift index 4df698aab..eb50bc1b6 100644 --- a/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift +++ b/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift @@ -72,6 +72,7 @@ struct StartChatScreen: View { .imageScale(.small) } .buttonStyle(FormButtonStyle(accessory: .navigationLink)) + .accessibilityLabel(A11yIdentifiers.startChatScreen.createRoom) } .compoundFormSection() } diff --git a/IntegrationTests/Sources/Common.swift b/IntegrationTests/Sources/Common.swift index 8f7ad1769..42a37a4b2 100644 --- a/IntegrationTests/Sources/Common.swift +++ b/IntegrationTests/Sources/Common.swift @@ -114,7 +114,7 @@ extension XCUIApplication { profileButton.forceTap() // Open the settings - let settingsButton = buttons["Settings"] + let settingsButton = buttons[A11yIdentifiers.homeScreen.settings] XCTAssertTrue(settingsButton.waitForExistence(timeout: 10.0)) settingsButton.tap() diff --git a/IntegrationTests/Sources/UserFlowTests.swift b/IntegrationTests/Sources/UserFlowTests.swift index dbcaa11bc..e5476224a 100644 --- a/IntegrationTests/Sources/UserFlowTests.swift +++ b/IntegrationTests/Sources/UserFlowTests.swift @@ -17,16 +17,84 @@ import XCTest class UserFlowTests: XCTestCase { - func testUserFlow() { - let app = Application.launch() - + private var app: XCUIApplication! + + override func setUp() { + app = Application.launch() app.login(currentTestCase: self) + } + + func testUserFlow() { + checkSettings() + + checkInvites() + + checkRoomCreation() // Open the first room in the list. let firstRoom = app.buttons.matching(NSPredicate(format: "identifier BEGINSWITH %@", A11yIdentifiers.homeScreen.roomNamePrefix)).firstMatch XCTAssertTrue(firstRoom.waitForExistence(timeout: 10.0)) firstRoom.tap() + checkAttachmentsPicker() + + checkTimelineItemActionMenu() + + checkRoomDetails() + + app.logout() + } + + private func checkInvites() { + // Open invites + let invitesButton = app.buttons[A11yIdentifiers.homeScreen.invites] + XCTAssertTrue(invitesButton.waitForExistence(timeout: 10.0)) + invitesButton.tap() + + // Go back to the room list + tapOnButton("All Chats") + } + + private func checkAttachmentsPicker() { + for identifier in [A11yIdentifiers.roomScreen.attachmentPickerPhotoLibrary, + A11yIdentifiers.roomScreen.attachmentPickerDocuments, + A11yIdentifiers.roomScreen.attachmentPickerCamera, + A11yIdentifiers.roomScreen.attachmentPickerLocation] { + tapOnButton(A11yIdentifiers.roomScreen.attachmentPicker) + tapOnButton(identifier) + tapOnButton("Cancel") + } + + // Open attachments picker + tapOnButton(A11yIdentifiers.roomScreen.attachmentPicker) + + // Open photo library picker + tapOnButton(A11yIdentifiers.roomScreen.attachmentPickerPhotoLibrary) + + // Tap on the first image + app.scrollViews.images.firstMatch.tap() + + // Cancel the upload flow + tapOnButton("Cancel") + } + + private func checkRoomCreation() { + tapOnButton(A11yIdentifiers.homeScreen.startChat) + + tapOnButton(A11yIdentifiers.startChatScreen.createRoom) + + tapOnButton(A11yIdentifiers.inviteUsersScreen.proceed) + + tapOnButton("Invite people") + + tapOnButton("Start chat") + + tapOnButton("Cancel") + + sleep(1) + } + + private func checkTimelineItemActionMenu() { // Long press on the last message let lastMessage = app.cells.firstMatch XCTAssertTrue(lastMessage.waitForExistence(timeout: 10.0)) @@ -36,16 +104,16 @@ class UserFlowTests: XCTestCase { let timelineItemActionMenu = app.otherElements[A11yIdentifiers.roomScreen.timelineItemActionMenu].firstMatch XCTAssertTrue(timelineItemActionMenu.waitForExistence(timeout: 10.0)) timelineItemActionMenu.swipeDown(velocity: .fast) - + } + + private func checkRoomDetails() { // Open the room details - let roomHeader = app.staticTexts["room-name"] + let roomHeader = app.staticTexts[A11yIdentifiers.roomScreen.name] XCTAssertTrue(roomHeader.waitForExistence(timeout: 10.0)) roomHeader.tap() // Open the room member details - let roomMembers = app.buttons["room_details-people"] - XCTAssertTrue(roomMembers.waitForExistence(timeout: 10.0)) - roomMembers.tap() + tapOnButton(A11yIdentifiers.roomDetailsScreen.people) // Open the first member's details let firstRoomMember = app.scrollViews.buttons.firstMatch @@ -53,25 +121,52 @@ class UserFlowTests: XCTestCase { firstRoomMember.tap() // Go back to the room member details - var backButton = app.buttons["People"] - XCTAssertTrue(backButton.waitForExistence(timeout: 10.0)) - backButton.tap() + tapOnButton("People") // Go back to the room details - backButton = app.buttons["Back"] - XCTAssertTrue(backButton.waitForExistence(timeout: 10.0)) - backButton.tap() + tapOnButton("Back") // Go back to the room - backButton = app.buttons["Back"] - XCTAssertTrue(backButton.waitForExistence(timeout: 10.0)) - backButton.tap() + tapOnButton("Back") // Go back to the room list - backButton = app.navigationBars.firstMatch.buttons["All Chats"] - XCTAssertTrue(backButton.waitForExistence(timeout: 10.0)) - backButton.tap() + tapOnButton("All Chats") + } + + private func checkSettings() { + let profileButton = app.buttons[A11yIdentifiers.homeScreen.userAvatar] - app.logout() + // `Failed to scroll to visible (by AX action) Button` https://stackoverflow.com/a/33534187/730924 + profileButton.forceTap() + + // Open the settings + tapOnButton(A11yIdentifiers.homeScreen.settings) + + // Open analytics + tapOnButton(A11yIdentifiers.settingsScreen.analytics) + + // Go back to settings + tapOnButton("Settings") + + // Open report a bug + tapOnButton(A11yIdentifiers.settingsScreen.reportBug) + + // Go back to settings + tapOnButton("Settings") + + // Open about + tapOnButton(A11yIdentifiers.settingsScreen.about) + + // Go back to settings + tapOnButton("Settings") + + // Close the settings + tapOnButton(A11yIdentifiers.settingsScreen.done) + } + + private func tapOnButton(_ identifier: String) { + let button = app.buttons[identifier] + XCTAssertTrue(button.waitForExistence(timeout: 10.0)) + button.tap() } }