summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Göransson <david.goransson@mullvad.net>2025-05-09 15:06:07 +0200
committerDavid Göransson <david.goransson@mullvad.net>2025-05-09 15:59:28 +0200
commit7d818e399b4bf63cb51deddf5c798adcb2a8cf11 (patch)
tree711bc5380b36dbc7d656eee7e7f36bdbff58debd
parent3c8fc9ef9cffb93dac3d2ebcac49af144e5f8225 (diff)
downloadmullvadvpn-7d818e399b4bf63cb51deddf5c798adcb2a8cf11.tar.xz
mullvadvpn-7d818e399b4bf63cb51deddf5c798adcb2a8cf11.zip
Fix flaky device management test
The device mangement test would fail because it expect the device to be removed however it was in a loading state while API request was being made. This commit allows it to be visible intiailly (loading) and then expects it to be removed.
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/extension/UiAutomatorExtensions.kt17
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/AccountPage.kt5
-rw-r--r--android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/ManageDevicesMockApiTest.kt31
3 files changed, 39 insertions, 14 deletions
diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/extension/UiAutomatorExtensions.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/extension/UiAutomatorExtensions.kt
index cb186463cd..aa993025f5 100644
--- a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/extension/UiAutomatorExtensions.kt
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/extension/UiAutomatorExtensions.kt
@@ -9,6 +9,7 @@ import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.UiObject2Condition
import androidx.test.uiautomator.Until
import co.touchlab.kermit.Logger
+import java.lang.Thread.sleep
import java.util.regex.Pattern
import net.mullvad.mullvadvpn.test.common.constant.DEFAULT_TIMEOUT
import net.mullvad.mullvadvpn.test.common.constant.LONG_TIMEOUT
@@ -40,6 +41,22 @@ fun UiDevice.findObjectWithTimeout(
return foundObject
}
+fun UiDevice.expectObjectToDisappearWithTimeout(
+ selector: BySelector,
+ timeout: Long = DEFAULT_TIMEOUT,
+) {
+ val sleepInterval = 100L
+ val startTime = System.currentTimeMillis()
+
+ while (null != findObject(selector)) {
+ val elapsedTime = System.currentTimeMillis() - startTime
+ if (elapsedTime > timeout) {
+ error("Object is still visible after timeout")
+ }
+ sleep(sleepInterval)
+ }
+}
+
fun UiDevice.clickObjectAwaitCondition(
selector: BySelector,
condition: UiObject2Condition<Boolean>,
diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/AccountPage.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/AccountPage.kt
index db4a963648..67183b68f6 100644
--- a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/AccountPage.kt
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/AccountPage.kt
@@ -1,6 +1,7 @@
package net.mullvad.mullvadvpn.test.common.page
import androidx.test.uiautomator.By
+import net.mullvad.mullvadvpn.lib.ui.tag.MANAGE_DEVICES_BUTTON_TEST_TAG
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
class AccountPage internal constructor() : Page() {
@@ -10,6 +11,10 @@ class AccountPage internal constructor() : Page() {
uiDevice.findObjectWithTimeout(By.text("Account"))
}
+ fun clickManageDevices() {
+ uiDevice.findObject(By.res(MANAGE_DEVICES_BUTTON_TEST_TAG)).click()
+ }
+
fun clickLogOut() {
uiDevice.findObjectWithTimeout(logOutSelector).click()
}
diff --git a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/ManageDevicesMockApiTest.kt b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/ManageDevicesMockApiTest.kt
index 6b2248a6b0..1b087ec0fe 100644
--- a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/ManageDevicesMockApiTest.kt
+++ b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/ManageDevicesMockApiTest.kt
@@ -2,11 +2,14 @@ package net.mullvad.mullvadvpn.test.mockapi
import androidx.test.uiautomator.By
import java.time.ZonedDateTime
-import net.mullvad.mullvadvpn.lib.ui.tag.MANAGE_DEVICES_BUTTON_TEST_TAG
import net.mullvad.mullvadvpn.test.common.extension.clickAgreeOnPrivacyDisclaimer
import net.mullvad.mullvadvpn.test.common.extension.clickAllowOnNotificationPermissionPromptIfApiLevel33AndAbove
import net.mullvad.mullvadvpn.test.common.extension.dismissChangelogDialogIfShown
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
+import net.mullvad.mullvadvpn.test.common.page.AccountPage
+import net.mullvad.mullvadvpn.test.common.page.ConnectPage
+import net.mullvad.mullvadvpn.test.common.page.DeviceManagementPage
+import net.mullvad.mullvadvpn.test.common.page.on
import net.mullvad.mullvadvpn.test.mockapi.constant.ALMOST_FULL_DEVICE_LIST
import net.mullvad.mullvadvpn.test.mockapi.constant.DUMMY_DEVICE_NAME_1
import net.mullvad.mullvadvpn.test.mockapi.constant.DUMMY_ID_1
@@ -33,22 +36,22 @@ class ManageDevicesMockApiTest : MockApiTest() {
app.attemptLogin(validAccountNumber)
device.waitForIdle()
device.dismissChangelogDialogIfShown()
- app.ensureLoggedIn()
- app.clickAccountCog()
- device.findObject(By.res(MANAGE_DEVICES_BUTTON_TEST_TAG)).click()
- // Assert - current device is shown but not clickable
- val current = device.findObjectWithTimeout(By.text("Current device")).parent
- assertNull(current.findObject(By.clickable(true)))
+ on<ConnectPage> { clickAccount() }
- // Act - remove another device in the list
- val secondDevice = device.findObjectWithTimeout(By.text("Yellow Hat")).parent
- secondDevice.findObject(By.clickable(true)).click()
- app.clickActionButtonByText("Remove")
+ on<AccountPage> { clickManageDevices() }
- device.waitForIdle()
+ on<DeviceManagementPage> {
+ // Assert - current device is shown but not clickable
+ val current = uiDevice.findObjectWithTimeout(By.text("Current device")).parent
+ assertNull(current.findObject(By.clickable(true)))
+
+ removeDevice("Yellow Hat")
- // Assert - the other device is no longer shown
- assertNull(device.findObject(By.text("Yellow Hat")))
+ // Confirm removal of device
+ app.clickActionButtonByText("Remove")
+
+ expectDeviceToBeRemoved("Yellow Hat")
+ }
}
}