diff --git a/wire-ios/WireUITests/AccountManagementTests.swift b/wire-ios/WireUITests/AccountManagementTests.swift new file mode 100644 index 00000000000..7894437b53f --- /dev/null +++ b/wire-ios/WireUITests/AccountManagementTests.swift @@ -0,0 +1,92 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +import WireFoundation +import XCTest + +final class AccountManagementTests: WireUITestCase { + + @MainActor + func test_Account_Management_Lock_With_Passcode() async throws { + let passcode = UserGenerator.generateAppPasscode() + + let (_, teamOwner) = try await userHelper.registerUserAsTeamOwner() + let ownerAccessToken = try await userHelper.fetchAccessToken( + email: teamOwner.email, + password: teamOwner.password + ) + let teamID = try XCTUnwrap(teamOwner.teamID) + + let (_, teamMember) = try await userHelper.registerUsersAsTeamMember( + ownerAccessToken: ownerAccessToken, + teamID: teamID + ) + + let page = try await app.loginUser(email: teamMember.email, password: teamMember.password) + .acceptPopupOnTeamMemberSetup(with: self) + .setUsername(teamMember.username) + .openSettings() + .openOptionsMenu() + .enableLockWithPasscode() + .SetPasscode(passcode) + .backgroundAndResume(app: app, forDelay: 2) + + XCTAssertFalse( + page.conversationsPageLabel.exists, + "App incorrectly showing conversations page without app passcode" + ) + + _ = try page.enterPasscode(passcode) + } + + @MainActor + func test_Account_Management_Update_Email_Reset_password() async throws { + let updatedUserDetails = UserGenerator.generateUniqueUserInfo() + + let (_, teamOwner) = try await userHelper.registerUserAsTeamOwner() + let ownerAccessToken = try await userHelper.fetchAccessToken( + email: teamOwner.email, + password: teamOwner.password + ) + let teamID = try XCTUnwrap(teamOwner.teamID) + + let (_, teamMember) = try await userHelper.registerUsersAsTeamMember( + ownerAccessToken: ownerAccessToken, + teamID: teamID + ) + + let verifyEmailPage = try app.loginUser(email: teamMember.email, password: teamMember.password) + .acceptPopupOnTeamMemberSetup(with: self) + .setUsername(teamMember.username) + .openSettings() + .openAccountSettings() + .tapEmailField() + .updateEmailAndSave(with: updatedUserDetails.email) + + XCTAssertTrue( + app.staticTexts["Resend to \(updatedUserDetails.email)"].exists, + "Expected static text label 'Resend to \(updatedUserDetails.email)' to be visible, but it was missing." + ) + + let webViewPage = try verifyEmailPage.goBacktoAccountSetting() + .tapOnResetPasswordButton() + + XCTAssertTrue(webViewPage.webViewOpened(), "WebView didn't open") + + } +} diff --git a/wire-ios/WireUITests/Pages/AccountSettingsPage.swift b/wire-ios/WireUITests/Pages/AccountSettingsPage.swift index 7563a3fd060..a50aa8bafab 100644 --- a/wire-ios/WireUITests/Pages/AccountSettingsPage.swift +++ b/wire-ios/WireUITests/Pages/AccountSettingsPage.swift @@ -21,7 +21,11 @@ import XCTest class AccountSettingsPage: PageModel { override var pageMainElement: XCUIElement { - nameField + accountSettingsPageHeader + } + + var accountSettingsPageHeader: XCUIElement { + app.staticTexts["Account"] } var nameField: XCUIElement { @@ -60,6 +64,10 @@ class AccountSettingsPage: PageModel { app.descendants(matching: .any)["Back up or RestoreField"].firstMatch } + var resetPasswordButton: XCUIElement { + app.descendants(matching: .any)["Reset Password"].firstMatch + } + func getAccountName() -> String? { nameField.value as? String } @@ -81,6 +89,11 @@ class AccountSettingsPage: PageModel { return try SettingsPage() } + func tapEmailField() throws -> EmailUpdatePage { + emailField.tap() + return try EmailUpdatePage() + } + @discardableResult func logout() throws -> LogOutPage { logoutButton.tap() @@ -103,4 +116,9 @@ class AccountSettingsPage: PageModel { backToSettingsButton.tap() return try SettingsPage() } + + func tapOnResetPasswordButton() throws -> WebViewPage { + resetPasswordButton.tap() + return try WebViewPage() + } } diff --git a/wire-ios/WireUITests/Pages/EmailUpdatePage.swift b/wire-ios/WireUITests/Pages/EmailUpdatePage.swift new file mode 100644 index 00000000000..2cf9765e5e3 --- /dev/null +++ b/wire-ios/WireUITests/Pages/EmailUpdatePage.swift @@ -0,0 +1,47 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +import XCTest + +class EmailUpdatePage: PageModel { + + override var pageMainElement: XCUIElement { + emailField + } + + var emailField: XCUIElement { + app.descendants(matching: .any)["EmailField"].firstMatch + } + + var saveButton: XCUIElement { + app.buttons["Save"] + } + + func clearTextField(_ textfield: XCUIElement) { + textfield.doubleTap() + textfield.typeText("\u{8}") + } + + func updateEmailAndSave(with newEmail: String) throws -> VerifyEmailPage { + clearTextField(emailField) + emailField.typeText(newEmail) + saveButton.tap() + return try VerifyEmailPage() + } + +} diff --git a/wire-ios/WireUITests/Pages/OptionsOnSettingsPage.swift b/wire-ios/WireUITests/Pages/OptionsOnSettingsPage.swift index bf1be54c533..66f11715dbc 100644 --- a/wire-ios/WireUITests/Pages/OptionsOnSettingsPage.swift +++ b/wire-ios/WireUITests/Pages/OptionsOnSettingsPage.swift @@ -55,7 +55,12 @@ class OptionsOnSettingsPage: PageModel { func enterPasscode(_ pass: String) throws -> ConversationsPage { let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") try springboard.secureTextFields["Passcode field"].tapIfKeyboardNotFocused().typeText(pass) - springboard.keyboards.buttons["Done"].tap() + + if springboard.keyboards.buttons["Done"].exists { + springboard.keyboards.buttons["Done"].tap() + } else { + springboard.typeText(XCUIKeyboardKey.return.rawValue) + } return try ConversationsPage() } diff --git a/wire-ios/WireUITests/Pages/SaveBackupFileBottomSheetPage.swift b/wire-ios/WireUITests/Pages/SaveBackupFileBottomSheetPage.swift index 962395a102f..cfedd59be67 100644 --- a/wire-ios/WireUITests/Pages/SaveBackupFileBottomSheetPage.swift +++ b/wire-ios/WireUITests/Pages/SaveBackupFileBottomSheetPage.swift @@ -36,6 +36,7 @@ class SaveBackupFileBottomSheetPage: PageModel { let predicate = NSPredicate(format: "label BEGINSWITH %@", "WireBackup-\(dateString)") let element = app.otherElements.matching(predicate).firstMatch + guard element.waitForExistence(timeout: 3) else { return nil } return element.exists ? element.label : nil } diff --git a/wire-ios/WireUITests/Pages/VerifyEmailPage.swift b/wire-ios/WireUITests/Pages/VerifyEmailPage.swift new file mode 100644 index 00000000000..5a198834487 --- /dev/null +++ b/wire-ios/WireUITests/Pages/VerifyEmailPage.swift @@ -0,0 +1,45 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +import XCTest + +class VerifyEmailPage: PageModel { + + override var pageMainElement: XCUIElement { + verifyEmailPageLabel + } + + var verifyEmailPageLabel: XCUIElement { + app.staticTexts["Verify email"] + } + + var backToEmailUpdatePage: XCUIElement { + app.buttons["Email"] + } + + var backToAccountSetting: XCUIElement { + app.buttons["Account"] + } + + func goBacktoAccountSetting() throws -> AccountSettingsPage { + backToEmailUpdatePage.tap() + backToAccountSetting.tap() + return try AccountSettingsPage() + } + +} diff --git a/wire-ios/WireUITests/Pages/WebViewPage.swift b/wire-ios/WireUITests/Pages/WebViewPage.swift new file mode 100644 index 00000000000..2a009e482b9 --- /dev/null +++ b/wire-ios/WireUITests/Pages/WebViewPage.swift @@ -0,0 +1,37 @@ +// +// Wire +// Copyright (C) 2025 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +import XCTest + +class WebViewPage: PageModel { + + override var pageMainElement: XCUIElement { + webViewLabel + } + + private static let safariApp = XCUIApplication(bundleIdentifier: "com.apple.mobilesafari") + + var webViewLabel: XCUIElement { + Self.safariApp.webViews.firstMatch.staticTexts["Reset password"] + } + + @discardableResult + func webViewOpened(timeout: TimeInterval = 5) -> Bool { + Self.safariApp.webViews.firstMatch.waitForExistence(timeout: timeout) + } +} diff --git a/wire-ios/WireUITests/TeamManageTests.swift b/wire-ios/WireUITests/TeamManageTests.swift index 2438e7c359e..570bb38a2ec 100644 --- a/wire-ios/WireUITests/TeamManageTests.swift +++ b/wire-ios/WireUITests/TeamManageTests.swift @@ -188,37 +188,4 @@ final class TeamManageTests: WireUITestCase { "User \(teamMembers[0].name) is not present in group" ) } - - @MainActor - func test_Account_Management_Lock_With_Passcode() async throws { - let passcode = UserGenerator.generateAppPasscode() - - let (_, teamOwner) = try await userHelper.registerUserAsTeamOwner() - let ownerAccessToken = try await userHelper.fetchAccessToken( - email: teamOwner.email, - password: teamOwner.password - ) - let teamID = try XCTUnwrap(teamOwner.teamID) - - let (_, teamMember) = try await userHelper.registerUsersAsTeamMember( - ownerAccessToken: ownerAccessToken, - teamID: teamID - ) - - let page = try await app.loginUser(email: teamMember.email, password: teamMember.password) - .acceptPopupOnTeamMemberSetup(with: self) - .setUsername(teamMember.username) - .openSettings() - .openOptionsMenu() - .enableLockWithPasscode() - .SetPasscode(passcode) - .backgroundAndResume(app: app, forDelay: 2) - - XCTAssertFalse( - page.conversationsPageLabel.exists, - "App incorrectly showing conversations page without app passcode" - ) - - _ = try page.enterPasscode(passcode) - } }