summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorNiklas Berglund <niklas.berglund@gmail.com>2024-12-11 16:32:21 +0100
committerDavid Göransson <david.goransson@mullvad.net>2024-12-13 15:39:24 +0100
commitd34461affd206b7bf0ee76919f478f362056de5f (patch)
tree594220c0b1bc6db479a19f7ffa06d3d7c85a2f46 /android
parent37e90ed5ca9a3a094db531166404454cfcd81b33 (diff)
downloadmullvadvpn-d34461affd206b7bf0ee76919f478f362056de5f.tar.xz
mullvadvpn-d34461affd206b7bf0ee76919f478f362056de5f.zip
Migrate remaining e2e tests to POP
Diffstat (limited to 'android')
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt6
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/AccountPage.kt16
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/ConnectPage.kt5
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/MullvadWebsite.kt14
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/SettingsPage.kt5
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/VpnSettingsPage.kt6
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/WireGuardCustomPortDialog.kt30
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LeakTest.kt112
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LogoutTest.kt16
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/WebLinkTest.kt27
10 files changed, 164 insertions, 73 deletions
diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt
index ea9b761ea1..41fe28b68c 100644
--- a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt
@@ -39,11 +39,15 @@ class AppInteractor(
device.wait(Until.hasObject(By.pkg(targetPackageName).depth(0)), LONG_TIMEOUT)
}
- fun launchAndEnsureLoggedIn(accountNumber: String) {
+ fun launchAndEnsureOnLoginPage() {
launch()
device.clickAgreeOnPrivacyDisclaimer()
device.clickAllowOnNotificationPermissionPromptIfApiLevel33AndAbove()
waitForLoginPrompt()
+ }
+
+ fun launchAndEnsureLoggedIn(accountNumber: String) {
+ launchAndEnsureOnLoginPage()
attemptLogin(accountNumber)
device.dismissChangelogDialogIfShown()
ensureLoggedIn()
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
new file mode 100644
index 0000000000..db4a963648
--- /dev/null
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/AccountPage.kt
@@ -0,0 +1,16 @@
+package net.mullvad.mullvadvpn.test.common.page
+
+import androidx.test.uiautomator.By
+import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
+
+class AccountPage internal constructor() : Page() {
+ private val logOutSelector = By.text("Log out")
+
+ override fun assertIsDisplayed() {
+ uiDevice.findObjectWithTimeout(By.text("Account"))
+ }
+
+ fun clickLogOut() {
+ uiDevice.findObjectWithTimeout(logOutSelector).click()
+ }
+}
diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/ConnectPage.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/ConnectPage.kt
index 320c01d7aa..552fc17ee4 100644
--- a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/ConnectPage.kt
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/ConnectPage.kt
@@ -9,6 +9,7 @@ class ConnectPage internal constructor() : Page() {
private val cancelSelector = By.text("Cancel")
private val connectedSelector = By.text("CONNECTED")
private val connectingSelector = By.text("CONNECTING...")
+ private val disconnectedSelector = By.text("DISCONNECTED")
override fun assertIsDisplayed() {
uiDevice.findObjectWithTimeout(By.res(CONNECT_CARD_HEADER_TEST_TAG))
@@ -34,6 +35,10 @@ class ConnectPage internal constructor() : Page() {
uiDevice.findObjectWithTimeout(connectedSelector, timeout)
}
+ fun waitForDisconnectedLabel(timeout: Long = VERY_LONG_TIMEOUT) {
+ uiDevice.findObjectWithTimeout(disconnectedSelector, timeout)
+ }
+
fun waitForConnectingLabel() {
uiDevice.findObjectWithTimeout(connectingSelector)
}
diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/MullvadWebsite.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/MullvadWebsite.kt
new file mode 100644
index 0000000000..a9de089b24
--- /dev/null
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/MullvadWebsite.kt
@@ -0,0 +1,14 @@
+package net.mullvad.mullvadvpn.test.common.page
+
+import androidx.test.uiautomator.By
+import net.mullvad.mullvadvpn.test.common.constant.VERY_LONG_TIMEOUT
+import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
+
+class MullvadWebsite internal constructor() : Page() {
+ override fun assertIsDisplayed() {
+ uiDevice.findObjectWithTimeout(
+ selector = By.text("Mullvad help center"),
+ timeout = VERY_LONG_TIMEOUT,
+ )
+ }
+}
diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/SettingsPage.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/SettingsPage.kt
index 86a317d153..ebeb8eea4a 100644
--- a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/SettingsPage.kt
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/SettingsPage.kt
@@ -5,6 +5,7 @@ import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
class SettingsPage internal constructor() : Page() {
private val settingsSelector = By.text("Settings")
+ private val faqAndGuidesSelector = By.text("FAQs & Guides")
override fun assertIsDisplayed() {
uiDevice.findObjectWithTimeout(settingsSelector)
@@ -14,6 +15,10 @@ class SettingsPage internal constructor() : Page() {
uiDevice.findObjectWithTimeout(By.res(VPN_SETTINGS_CELL_TEST_TAG)).click()
}
+ fun clickFaqAndGuides() {
+ uiDevice.findObjectWithTimeout(faqAndGuidesSelector).click()
+ }
+
companion object {
const val VPN_SETTINGS_CELL_TEST_TAG = "vpn_settings_cell_test_tag"
}
diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/VpnSettingsPage.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/VpnSettingsPage.kt
index 698c84aa6b..1a74b80232 100644
--- a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/VpnSettingsPage.kt
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/VpnSettingsPage.kt
@@ -45,12 +45,18 @@ class VpnSettingsPage internal constructor() : Page() {
scrollView2.scrollUntil(Direction.DOWN, Until.hasObject(By.res(testTag)))
}
+ fun clickWireguardCustomPort() {
+ uiDevice.findObjectWithTimeout(By.res(WIREGUARD_CUSTOM_PORT_CELL_TEST_TAG)).click()
+ }
+
companion object {
const val SETTINGS_SCROLL_VIEW_TEST_TAG = "lazy_list_vpn_settings_test_tag"
const val WIREGUARD_OBFUSCATION_UDP_OVER_TCP_CELL_TEST_TAG =
"wireguard_obfuscation_udp_over_tcp_cell_test_tag"
const val WIREGUARD_OBFUSCATION_OFF_CELL_TEST_TAG =
"wireguard_obfuscation_off_cell_test_tag"
+ const val WIREGUARD_CUSTOM_PORT_CELL_TEST_TAG =
+ "lazy_list_wireguard_custom_port_text_test_tag"
const val SWITCH_TEST_TAG = "switch_test_tag"
}
}
diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/WireGuardCustomPortDialog.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/WireGuardCustomPortDialog.kt
new file mode 100644
index 0000000000..ee112a5d46
--- /dev/null
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/WireGuardCustomPortDialog.kt
@@ -0,0 +1,30 @@
+package net.mullvad.mullvadvpn.test.common.page
+
+import androidx.test.uiautomator.By
+import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
+
+class WireGuardCustomPortDialog internal constructor() : Page() {
+ private val textFieldLabelSelector = By.text("Enter port")
+ private val setPortSelector = By.text("Set port")
+ private val cancelSelector = By.text("Cancel")
+
+ override fun assertIsDisplayed() {
+ uiDevice.findObjectWithTimeout(textFieldLabelSelector)
+ }
+
+ fun enterCustomPort(port: String) {
+ uiDevice.findObjectWithTimeout(textFieldLabelSelector).parent.text = port
+ }
+
+ fun clickSetPort() {
+ uiDevice.findObjectWithTimeout(setPortSelector).click()
+ }
+
+ fun clickCancel() {
+ uiDevice.findObjectWithTimeout(cancelSelector).click()
+ }
+
+ companion object {
+ const val TEXT_FIELD_TEST_TAG = "custom_port_dialog_input_test_tag"
+ }
+}
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LeakTest.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LeakTest.kt
index 47f2c72068..51b6d84708 100644
--- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LeakTest.kt
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LeakTest.kt
@@ -1,16 +1,17 @@
package net.mullvad.mullvadvpn.test.e2e
-import androidx.test.uiautomator.By
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
-import net.mullvad.mullvadvpn.compose.test.EXPAND_BUTTON_TEST_TAG
-import net.mullvad.mullvadvpn.compose.test.SELECT_LOCATION_BUTTON_TEST_TAG
-import net.mullvad.mullvadvpn.compose.test.SWITCH_TEST_TAG
-import net.mullvad.mullvadvpn.compose.test.TOP_BAR_SETTINGS_BUTTON
-import net.mullvad.mullvadvpn.test.common.constant.VERY_LONG_TIMEOUT
-import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
import net.mullvad.mullvadvpn.test.common.misc.Attachment
+import net.mullvad.mullvadvpn.test.common.page.ConnectPage
+import net.mullvad.mullvadvpn.test.common.page.SelectLocationPage
+import net.mullvad.mullvadvpn.test.common.page.SettingsPage
+import net.mullvad.mullvadvpn.test.common.page.SystemVpnConfigurationAlert
+import net.mullvad.mullvadvpn.test.common.page.TopBar
+import net.mullvad.mullvadvpn.test.common.page.VpnSettingsPage
+import net.mullvad.mullvadvpn.test.common.page.WireGuardCustomPortDialog
+import net.mullvad.mullvadvpn.test.common.page.on
import net.mullvad.mullvadvpn.test.common.rule.ForgetAllVpnAppsInSettingsTestRule
import net.mullvad.mullvadvpn.test.e2e.annotations.HasDependencyOnLocalAPI
import net.mullvad.mullvadvpn.test.e2e.misc.AccountTestRule
@@ -34,18 +35,22 @@ class LeakTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
@BeforeEach
fun setupVPNSettings() {
app.launchAndEnsureLoggedIn(accountTestRule.validAccountNumber)
- device.findObjectWithTimeout(By.res(TOP_BAR_SETTINGS_BUTTON)).click()
- device.findObjectWithTimeout(By.text("VPN settings")).click()
- val localNetworkSharingCell =
- device.findObjectWithTimeout(By.text("Local network sharing")).parent
- val localNetworkSharingSwitch =
- localNetworkSharingCell.findObjectWithTimeout(By.res(SWITCH_TEST_TAG))
+ on<TopBar> { clickSettings() }
- localNetworkSharingSwitch.click()
+ on<SettingsPage> { clickVpnSettings() }
- // Only use port 51820 to make packet capture more deterministic
- device.findObjectWithTimeout(By.text("51820")).click()
+ on<VpnSettingsPage> {
+ clickLocalNetworkSharingSwitch()
+ clickWireguardCustomPort()
+ }
+
+ on<WireGuardCustomPortDialog> {
+ enterCustomPort("51820")
+ clickSetPort()
+ }
+
+ on<VpnSettingsPage> {}
device.pressBack()
device.pressBack()
@@ -56,18 +61,26 @@ class LeakTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
fun testNegativeLeak() =
runBlocking<Unit> {
app.launch()
- device.findObjectWithTimeout(By.text("DISCONNECTED"))
- val targetIpAddress = BuildConfig.TRAFFIC_GENERATION_IP_ADDRESS
- val targetPort = 80
+ on<ConnectPage> {
+ waitForDisconnectedLabel()
+
+ clickSelectLocation()
+ }
- device.findObjectWithTimeout(By.res(SELECT_LOCATION_BUTTON_TEST_TAG)).click()
- clickLocationExpandButton(DEFAULT_COUNTRY)
- clickLocationExpandButton(DEFAULT_CITY)
- device.findObjectWithTimeout(By.text(DEFAULT_RELAY)).click()
- device.findObjectWithTimeout(By.text("OK")).click()
- device.findObjectWithTimeout(By.text("CONNECTED"), VERY_LONG_TIMEOUT)
+ on<SelectLocationPage> {
+ clickLocationExpandButton(DEFAULT_COUNTRY)
+ clickLocationExpandButton(DEFAULT_CITY)
+ clickLocationCell(DEFAULT_RELAY)
+ }
+ on<SystemVpnConfigurationAlert> { clickOk() }
+
+ on<ConnectPage> { waitForConnectedLabel() }
+
+ // Capture generated traffic to a specific host
+ val targetIpAddress = BuildConfig.TRAFFIC_GENERATION_IP_ADDRESS
+ val targetPort = 80
val captureResult =
PacketCapture().capturePackets {
TrafficGenerator(targetIpAddress, targetPort).generateTraffic(10.milliseconds) {
@@ -76,11 +89,10 @@ class LeakTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
}
}
- device.findObjectWithTimeout(By.text("Disconnect")).click()
+ on<ConnectPage> { clickDisconnect() }
val capturedStreams = captureResult.streams
val capturedPcap = captureResult.pcap
-
val timestamp = System.currentTimeMillis()
Attachment.saveAttachment("capture-testNegativeLeak-$timestamp.pcap", capturedPcap)
@@ -93,37 +105,51 @@ class LeakTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
fun testShouldHaveNegativeLeak() =
runBlocking<Unit> {
app.launch()
- device.findObjectWithTimeout(By.text("DISCONNECTED"))
- val targetIpAddress = BuildConfig.TRAFFIC_GENERATION_IP_ADDRESS
- val targetPort = 80
+ on<ConnectPage> {
+ waitForDisconnectedLabel()
+
+ clickSelectLocation()
+ }
+
+ on<SelectLocationPage> {
+ clickLocationExpandButton(DEFAULT_COUNTRY)
+ clickLocationExpandButton(DEFAULT_CITY)
+ clickLocationCell(DEFAULT_RELAY)
+ }
- device.findObjectWithTimeout(By.res(SELECT_LOCATION_BUTTON_TEST_TAG)).click()
- delay(1000.milliseconds)
- clickLocationExpandButton(DEFAULT_COUNTRY)
- clickLocationExpandButton(DEFAULT_CITY)
- device.findObjectWithTimeout(By.text(DEFAULT_RELAY)).click()
- device.findObjectWithTimeout(By.text("OK")).click()
- device.findObjectWithTimeout(By.text("CONNECTED"), VERY_LONG_TIMEOUT)
+ on<SystemVpnConfigurationAlert> { clickOk() }
+ on<ConnectPage> { waitForConnectedLabel() }
+
+ // Capture generated traffic to a specific host
+ val targetIpAddress = BuildConfig.TRAFFIC_GENERATION_IP_ADDRESS
+ val targetPort = 80
val captureResult: PacketCaptureResult =
PacketCapture().capturePackets {
TrafficGenerator(targetIpAddress, targetPort).generateTraffic(10.milliseconds) {
delay(
3000.milliseconds
) // Give it some time for generating traffic in tunnel
- device.findObjectWithTimeout(By.text("Disconnect")).click()
+
+ on<ConnectPage> { clickDisconnect() }
+
delay(
2000.milliseconds
) // Give it some time to leak traffic outside of tunnel
- device.findObjectWithTimeout(By.text("Connect")).click()
+
+ on<ConnectPage> {
+ clickConnect()
+ waitForConnectedLabel()
+ }
+
delay(
3000.milliseconds
) // Give it some time for generating traffic in tunnel
}
}
- device.findObjectWithTimeout(By.text("Disconnect")).click()
+ on<ConnectPage> { clickDisconnect() }
val capturedStreams = captureResult.streams
val capturedPcap = captureResult.pcap
@@ -133,10 +159,4 @@ class LeakTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
val leakRules = listOf(NoTrafficToHostRule(targetIpAddress))
LeakCheck.assertLeaks(capturedStreams, leakRules)
}
-
- private fun clickLocationExpandButton(locationName: String) {
- val locationCell = device.findObjectWithTimeout(By.text(locationName)).parent.parent
- val expandButton = locationCell.findObjectWithTimeout(By.res(EXPAND_BUTTON_TEST_TAG))
- expandButton.click()
- }
}
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LogoutTest.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LogoutTest.kt
index 7a8c8818f4..af03c462c6 100644
--- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LogoutTest.kt
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LogoutTest.kt
@@ -1,9 +1,10 @@
package net.mullvad.mullvadvpn.test.e2e
-import androidx.test.uiautomator.By
-import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
+import net.mullvad.mullvadvpn.test.common.page.AccountPage
+import net.mullvad.mullvadvpn.test.common.page.LoginPage
+import net.mullvad.mullvadvpn.test.common.page.TopBar
+import net.mullvad.mullvadvpn.test.common.page.on
import net.mullvad.mullvadvpn.test.e2e.misc.AccountTestRule
-import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.RegisterExtension
@@ -16,11 +17,10 @@ class LogoutTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
// Given
app.launchAndEnsureLoggedIn(accountTestRule.validAccountNumber)
- // When
- app.clickAccountCog()
- app.clickActionButtonByText("Log out")
+ on<TopBar> { clickAccount() }
- // Then
- assertNotNull(device.findObjectWithTimeout(By.text("Login")))
+ on<AccountPage> { clickLogOut() }
+
+ on<LoginPage>()
}
}
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/WebLinkTest.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/WebLinkTest.kt
index 1b774d1134..402939db7a 100644
--- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/WebLinkTest.kt
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/WebLinkTest.kt
@@ -1,31 +1,22 @@
package net.mullvad.mullvadvpn.test.e2e
-import androidx.test.uiautomator.By
import net.mullvad.mullvadvpn.test.common.annotation.SkipForFlavors
-import net.mullvad.mullvadvpn.test.common.constant.VERY_LONG_TIMEOUT
-import net.mullvad.mullvadvpn.test.common.extension.clickAgreeOnPrivacyDisclaimer
-import net.mullvad.mullvadvpn.test.common.extension.clickAllowOnNotificationPermissionPromptIfApiLevel33AndAbove
-import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
+import net.mullvad.mullvadvpn.test.common.page.MullvadWebsite
+import net.mullvad.mullvadvpn.test.common.page.SettingsPage
+import net.mullvad.mullvadvpn.test.common.page.TopBar
+import net.mullvad.mullvadvpn.test.common.page.on
import org.junit.jupiter.api.Test
class WebLinkTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
@Test
@SkipForFlavors(currentFlavor = BuildConfig.FLAVOR_billing, "play")
fun testOpenFaqFromApp() {
- // Given
- app.launch()
+ app.launchAndEnsureOnLoginPage()
- // When
- device.clickAgreeOnPrivacyDisclaimer()
- device.clickAllowOnNotificationPermissionPromptIfApiLevel33AndAbove()
- device.findObjectWithTimeout(By.text("Login"))
- app.clickSettingsCog()
- app.clickListItemByText("FAQs & Guides")
+ on<TopBar> { clickSettings() }
- // Then
- device.findObjectWithTimeout(
- selector = By.text("Mullvad help center"),
- timeout = VERY_LONG_TIMEOUT,
- )
+ on<SettingsPage> { clickFaqAndGuides() }
+
+ on<MullvadWebsite>()
}
}