diff --git a/.github/workflows/ios-end-to-end-tests-settings-migration.yml b/.github/workflows/ios-end-to-end-tests-settings-migration.yml deleted file mode 100644 index fb59434b27ef..000000000000 --- a/.github/workflows/ios-end-to-end-tests-settings-migration.yml +++ /dev/null @@ -1,126 +0,0 @@ ---- -name: iOS settings migration tests -concurrency: - group: ios-end-to-end-tests - cancel-in-progress: false -permissions: - contents: read -on: - workflow_dispatch: - schedule: - # At midnight every day. - # Notifications for scheduled workflows are sent to the user who last modified the cron - # syntax in the workflow file. If you update this you must have notifications for - # Github Actions enabled, so these don't go unnoticed. - # https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/notifications-for-workflow-runs - - cron: '0 0 * * *' -env: - TEST_DEVICE_UDID: 00008130-0019181022F3803A -jobs: - test: - name: Settings migration end to end tests - runs-on: [self-hosted, macOS, ios-test] - env: - OLD_APP_COMMIT_HASH: 895b7d98825e678f5d7023d5ea3c9b7beee89280 - steps: - - name: Configure Rust - uses: actions-rs/toolchain@v1.0.6 - with: - toolchain: stable - override: true - target: aarch64-apple-ios - - - name: Uninstall app - timeout-minutes: 5 - run: ios-deploy --id ${{ env.TEST_DEVICE_UDID }} --uninstall_only --bundle_id net.mullvad.MullvadVPN - - - name: Checkout old repository version - uses: actions/checkout@v4 - with: - ref: ${{ env.OLD_APP_COMMIT_HASH }} - - - name: Change DNS settings on old app version - uses: ./.github/actions/ios-end-to-end-tests - with: - ios_device_pin_code: ${{ secrets.IOS_DEVICE_PIN_CODE }} - test_device_identifier_uuid: ${{ secrets.IOS_TEST_DEVICE_IDENTIFIER_UUID }} - has_time_account_number: ${{ secrets.IOS_HAS_TIME_ACCOUNT_NUMBER_PRODUCTION }} - no_time_account_number: ${{ secrets.IOS_NO_TIME_ACCOUNT_NUMBER_PRODUCTION }} - test_device_udid: ${{ env.TEST_DEVICE_UDID }} - xcode_test_plan: 'MullvadVPNUITestsChangeDNSSettings' - partner_api_token: ${{ secrets.STAGEMOLE_PARTNER_AUTH }} - - - name: Store test report for changing DNS settings - uses: actions/upload-artifact@v4 - if: always() - with: - name: test-report-change-dns-settings - path: ios/test-report/junit.xml - - - name: Checkout repository to get the current app version - uses: actions/checkout@v4 - - - name: Verify DNS settings still changed on current app version - uses: ./.github/actions/ios-end-to-end-tests - if: always() - with: - ios_device_pin_code: ${{ secrets.IOS_DEVICE_PIN_CODE }} - test_device_identifier_uuid: ${{ secrets.IOS_TEST_DEVICE_IDENTIFIER_UUID }} - has_time_account_number: ${{ secrets.IOS_HAS_TIME_ACCOUNT_NUMBER_PRODUCTION }} - no_time_account_number: ${{ secrets.IOS_NO_TIME_ACCOUNT_NUMBER_PRODUCTION }} - test_device_udid: ${{ env.TEST_DEVICE_UDID }} - partner_api_token: ${{ secrets.STAGEMOLE_PARTNER_AUTH }} - xcode_test_plan: 'MullvadVPNUITestsVerifyDNSSettingsChanged' - - - name: Store test report for verifying DNS settings - uses: actions/upload-artifact@v4 - if: always() - with: - name: test-report-verify-dns-settings - path: ios/test-report/junit.xml - - - name: Checkout old repository version - uses: actions/checkout@v4 - with: - ref: ${{ env.OLD_APP_COMMIT_HASH }} - - - name: Change all other settings on old app version - uses: ./.github/actions/ios-end-to-end-tests - if: always() - with: - ios_device_pin_code: ${{ secrets.IOS_DEVICE_PIN_CODE }} - test_device_identifier_uuid: ${{ secrets.IOS_TEST_DEVICE_IDENTIFIER_UUID }} - has_time_account_number: ${{ secrets.IOS_HAS_TIME_ACCOUNT_NUMBER_PRODUCTION }} - no_time_account_number: ${{ secrets.IOS_NO_TIME_ACCOUNT_NUMBER_PRODUCTION }} - test_device_udid: ${{ env.TEST_DEVICE_UDID }} - partner_api_token: ${{ secrets.STAGEMOLE_PARTNER_AUTH }} - xcode_test_plan: 'MullvadVPNUITestsChangeSettings' - - - name: Store test report for changing all settings - uses: actions/upload-artifact@v4 - if: always() - with: - name: test-report-change-all-other-settings - path: ios/test-report/junit.xml - - - name: Checkout repository to get the current app version - uses: actions/checkout@v4 - - - name: Verify all other settings still changed on current app version - uses: ./.github/actions/ios-end-to-end-tests - if: always() - with: - ios_device_pin_code: ${{ secrets.IOS_DEVICE_PIN_CODE }} - test_device_identifier_uuid: ${{ secrets.IOS_TEST_DEVICE_IDENTIFIER_UUID }} - has_time_account_number: ${{ secrets.IOS_HAS_TIME_ACCOUNT_NUMBER_PRODUCTION }} - no_time_account_number: ${{ secrets.IOS_NO_TIME_ACCOUNT_NUMBER_PRODUCTION }} - test_device_udid: ${{ env.TEST_DEVICE_UDID }} - partner_api_token: ${{ secrets.STAGEMOLE_PARTNER_AUTH }} - xcode_test_plan: 'MullvadVPNUITestsVerifySettingsChanged' - - - name: Store test report for verifying all other settings - uses: actions/upload-artifact@v4 - if: always() - with: - name: test-report-verify-all-other-settings - path: ios/test-report/junit.xml diff --git a/.github/workflows/ios-end-to-end-tests.yml b/.github/workflows/ios-end-to-end-tests.yml index 4aa336dd9fdf..f177c28bf047 100644 --- a/.github/workflows/ios-end-to-end-tests.yml +++ b/.github/workflows/ios-end-to-end-tests.yml @@ -22,6 +22,10 @@ on: user_supplied_test_name: description: 'Only run test case/suite' required: false + commit_hash: + description: > + Specifies the repository commit to use; defaults to the current event's commit if not provided. + required: false jobs: set-up-outputs-directory: name: Set up outputs directory diff --git a/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift b/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift index 7f463069b8a5..11402ee6841e 100644 --- a/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift +++ b/ios/MullvadVPNUITests/Pages/VPNSettingsPage.swift @@ -133,21 +133,6 @@ class VPNSettingsPage: Page { return self } - @discardableResult func tapDaitaSwitch() -> Self { - app.cells[AccessibilityIdentifier.daitaSwitch] - .switches[AccessibilityIdentifier.customSwitch] - .tap() - let promptIsShown = app - .otherElements[AccessibilityIdentifier.daitaPromptAlert.rawValue] - .waitForExistence(timeout: 1.0) - - if promptIsShown { - DaitaPromptAlert(app) - .tapEnableAnyway() - } - return self - } - @discardableResult func verifyCustomWireGuardPortSelected(portNumber: String) -> Self { let cell = app.cells[AccessibilityIdentifier.wireGuardCustomPort] XCTAssertTrue(cell.isSelected) @@ -199,28 +184,6 @@ class VPNSettingsPage: Page { return self } - @discardableResult func verifyDaitaSwitchOn() -> Self { - let switchElement = app.cells[.daitaSwitch] - .switches[AccessibilityIdentifier.customSwitch] - - guard let switchValue = switchElement.value as? String else { - XCTFail("Failed to read switch state") - return self - } - - XCTAssertEqual(switchValue, "1") - return self - } - - @discardableResult func tapDaitaSwitchIfOn() -> Self { - let switchElement = app.cells[.daitaSwitch].switches[AccessibilityIdentifier.customSwitch] - - if switchElement.value as? String == "1" { - tapDaitaSwitch() - } - return self - } - @discardableResult func tapMultihopSwitchIfOn() -> Self { let switchElement = app.cells[.multihopSwitch].switches[AccessibilityIdentifier.customSwitch] diff --git a/ios/MullvadVPNUITests/README.md b/ios/MullvadVPNUITests/README.md index e2386f7e43de..dfab60742e9f 100644 --- a/ios/MullvadVPNUITests/README.md +++ b/ios/MullvadVPNUITests/README.md @@ -9,7 +9,6 @@ There are five workflows running tests: - [ios-end-to-end-tests-nightly.yml](https://github.com/mullvad/mullvadvpn-app/actions/workflows/ios-end-to-end-tests-nightly.yml) - scheduled nightly test run, running all tests. - [ios-end-to-end-tests-merge-to-main.yml](https://github.com/mullvad/mullvadvpn-app/actions/workflows/ios-end-to-end-tests-merge-to-main.yml) - automatically triggered by a PR merge to `main`. - [ios-end-to-end-tests-api.yml](https://github.com/mullvad/mullvadvpn-app/actions/workflows/ios-end-to-end-tests-api.yml) - manually triggered tests focusing on making sure the API is functioning as intended on stagemole. - - [ios-end-to-end-tests-settings-migration.yml](https://github.com/mullvad/mullvadvpn-app/actions/workflows/ios-end-to-end-tests-settings-migration.yml) - for now this is still manually triggered. Tests installing older version of the app, changing settings, upgrading the app and verifying that settings were correctly migrated. ## Adding more tests When adding more files with test suites they must be added to the `MullvadVPNUITestsAll` test plan and also added to the appropriate node(s) in `ios/MullvadVPNUITests/tests.json` file in order to run in CI. For new test cases in already existing test suite nothing needs to be done. The test case/suite values in `tests.json` translate to input for `xcodebuild -only-testing` which is in the format `//`. The GitHub actions workflow will add the `` part so only `/` is required, where `` is optional. So for example `AccountTests` and `AccountTests/testLogin` are both valid values. @@ -33,7 +32,7 @@ The test device must be on the office WiFi `app-team-ios-tests` in order to be a 1. Make sure device is added to provisioning profiles 2. Enable developer mode 3. Disable passcode in iOS settings - otherwise tests cannot be started without manually entering passcode -4. Set the value of `TEST_DEVICE_UDID` to the UDID of the test device in `ios-end-to-end-tests.yml` and `ios-end-to-end-tests-settings-migration.yml`. +4. Set the value of `TEST_DEVICE_UDID` to the UDID of the test device in `ios-end-to-end-tests.yml`. 5. Make sure the test device is connected to the WiFi `app-team-ios-tests` 6. Make sure iCloud syncing of keychain is off on the device so that the device isn't getting WiFi passwords from another device causing it to sometimes connect to another WiFi. 7. After the device is set up download updated provisioning profiles on the GitHub runner computer(Download manual profiles in Xcode settings) @@ -69,14 +68,10 @@ The test device must be on the office WiFi `app-team-ios-tests` in order to be a - `PARTNER_API_TOKEN` - secret token for partner API. Optional and only intended to be used in CI when running tests against staging environment. ### Specifying which tests run when in CI -Which tests run when is specified in `tests.json`(See _Adding more tests_). Settings migration is an exception, it uses four different test plans and a separate workflow `ios-end-to-end-tests-settings-migration.yml` which executes the test plans in order, do not reinstall the app in between runs but upgrades the app after changing settings: -* `MullvadVPNUITestsChangeDNSSettings` - Change settings for using custom DNS -* `MullvadVPNUITestsVerifyDNSSettingsChanged` - Verify custom DNS settings still changed -* `MullvadVPNUITestsChangeSettings` - Change all settings except custom DNS setting -* `MullvadVPNUITestsVerifySettingsChanged` - Verify all settings except custom DNS setting still changed +Which tests run when is specified in `tests.json`(See _Adding more tests_). ### Current test devices -Currently we are using an iPhone 15 Pro(UDID `00008130-0019181022F3803A`) running iOS 17. +Currently we are using an iPhone 15 Pro(UDID `00008130-0019181022F3803A`) running iOS 17.3.1. ## APIs used The iOS team NUC is hosting APIs consumed by tests: diff --git a/ios/MullvadVPNUITests/SettingsMigrationTests.swift b/ios/MullvadVPNUITests/SettingsMigrationTests.swift index 0de0e5931938..dd6e55ce6dd7 100644 --- a/ios/MullvadVPNUITests/SettingsMigrationTests.swift +++ b/ios/MullvadVPNUITests/SettingsMigrationTests.swift @@ -9,15 +9,32 @@ import Foundation import XCTest -/* - Settings migration is an exception, it uses four different test plans and a separate workflow - `ios-end-to-end-tests-settings-migration.yml` which executes the test plans in order, - do not reinstall the app in between runs but upgrades the app after changing settings: - * `MullvadVPNUITestsChangeDNSSettings` - Change settings for using custom DNS - * `MullvadVPNUITestsVerifyDNSSettingsChanged` - Verify custom DNS settings still changed - * `MullvadVPNUITestsChangeSettings` - Change all settings except custom DNS setting - * `MullvadVPNUITestsVerifySettingsChanged` - Verify all settings except custom DNS setting still changed - */ +/// Pre-Release iOS Settings Migration Testing Instructions +/// +/// Before releasing a new version, ensure the settings migration process works as expected. +/// Follow these steps to validate that user settings persist correctly across app updates: +/// +/// 1. Remove the installed app: +/// Uninstall the current app from the test device to ensure a clean environment. +/// 2. Switch to an older released version: +/// Checkout an app version released approximately 6 months ago for testing migration over a meaningful time span. +/// 3. Run `testChangeCustomDNSSettings`: +/// Modify DNS settings in the older app version to simulate real-world user interactions. +/// 4. Checkout the release branch: +/// Switch to the branch containing the new app version to be released. +/// - Run `testVerifyCustomDNSSettingsStillChanged`: +/// Verify that DNS settings changed in step 3 persist after upgrading. +/// 5. Return to the older version: +/// Checkout the same older version used in step 2 to continue testing additional settings. +/// 6. Run `testChangeVPNSettings`: +/// Modify VPN-related settings in the older app version. +/// 7. Switch back to the release branch: +/// Return to the branch checked out in step 4. +/// - Run `testVerifySettingsStillChanged`: +/// Confirm that VPN settings changed in step 6 persist after upgrading. +/// +/// These steps ensure the app's settings migration logic is robust and reliable, +/// providing a seamless user experience during upgrades. class SettingsMigrationTests: BaseUITestCase { let customDNSServerIPAddress = "123.123.123.123" let wireGuardPort = "4001" @@ -121,7 +138,6 @@ class SettingsMigrationTests: BaseUITestCase { .tapUDPOverTCPPort80Cell() .tapQuantumResistantTunnelExpandButton() .tapQuantumResistantTunnelOnCell() - .tapDaitaSwitch() .tapMultihopSwitch() } @@ -154,7 +170,6 @@ class SettingsMigrationTests: BaseUITestCase { .verifyUDPOverTCPPort80Selected() .tapQuantumResistantTunnelExpandButton() .verifyQuantumResistantTunnelOnSelected() - .verifyDaitaSwitchOn() .verifyMultihopSwitchOn() } }