Skip to content

Commit 8de6bf8

Browse files
committed
Merge branch 'migrate-more-test-classes-to-POP'
2 parents 37e90ed + d34461a commit 8de6bf8

File tree

10 files changed

+164
-73
lines changed

10 files changed

+164
-73
lines changed

android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt

+5-1
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,15 @@ class AppInteractor(
3939
device.wait(Until.hasObject(By.pkg(targetPackageName).depth(0)), LONG_TIMEOUT)
4040
}
4141

42-
fun launchAndEnsureLoggedIn(accountNumber: String) {
42+
fun launchAndEnsureOnLoginPage() {
4343
launch()
4444
device.clickAgreeOnPrivacyDisclaimer()
4545
device.clickAllowOnNotificationPermissionPromptIfApiLevel33AndAbove()
4646
waitForLoginPrompt()
47+
}
48+
49+
fun launchAndEnsureLoggedIn(accountNumber: String) {
50+
launchAndEnsureOnLoginPage()
4751
attemptLogin(accountNumber)
4852
device.dismissChangelogDialogIfShown()
4953
ensureLoggedIn()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package net.mullvad.mullvadvpn.test.common.page
2+
3+
import androidx.test.uiautomator.By
4+
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
5+
6+
class AccountPage internal constructor() : Page() {
7+
private val logOutSelector = By.text("Log out")
8+
9+
override fun assertIsDisplayed() {
10+
uiDevice.findObjectWithTimeout(By.text("Account"))
11+
}
12+
13+
fun clickLogOut() {
14+
uiDevice.findObjectWithTimeout(logOutSelector).click()
15+
}
16+
}

android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/ConnectPage.kt

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ class ConnectPage internal constructor() : Page() {
99
private val cancelSelector = By.text("Cancel")
1010
private val connectedSelector = By.text("CONNECTED")
1111
private val connectingSelector = By.text("CONNECTING...")
12+
private val disconnectedSelector = By.text("DISCONNECTED")
1213

1314
override fun assertIsDisplayed() {
1415
uiDevice.findObjectWithTimeout(By.res(CONNECT_CARD_HEADER_TEST_TAG))
@@ -34,6 +35,10 @@ class ConnectPage internal constructor() : Page() {
3435
uiDevice.findObjectWithTimeout(connectedSelector, timeout)
3536
}
3637

38+
fun waitForDisconnectedLabel(timeout: Long = VERY_LONG_TIMEOUT) {
39+
uiDevice.findObjectWithTimeout(disconnectedSelector, timeout)
40+
}
41+
3742
fun waitForConnectingLabel() {
3843
uiDevice.findObjectWithTimeout(connectingSelector)
3944
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package net.mullvad.mullvadvpn.test.common.page
2+
3+
import androidx.test.uiautomator.By
4+
import net.mullvad.mullvadvpn.test.common.constant.VERY_LONG_TIMEOUT
5+
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
6+
7+
class MullvadWebsite internal constructor() : Page() {
8+
override fun assertIsDisplayed() {
9+
uiDevice.findObjectWithTimeout(
10+
selector = By.text("Mullvad help center"),
11+
timeout = VERY_LONG_TIMEOUT,
12+
)
13+
}
14+
}

android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/SettingsPage.kt

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
55

66
class SettingsPage internal constructor() : Page() {
77
private val settingsSelector = By.text("Settings")
8+
private val faqAndGuidesSelector = By.text("FAQs & Guides")
89

910
override fun assertIsDisplayed() {
1011
uiDevice.findObjectWithTimeout(settingsSelector)
@@ -14,6 +15,10 @@ class SettingsPage internal constructor() : Page() {
1415
uiDevice.findObjectWithTimeout(By.res(VPN_SETTINGS_CELL_TEST_TAG)).click()
1516
}
1617

18+
fun clickFaqAndGuides() {
19+
uiDevice.findObjectWithTimeout(faqAndGuidesSelector).click()
20+
}
21+
1722
companion object {
1823
const val VPN_SETTINGS_CELL_TEST_TAG = "vpn_settings_cell_test_tag"
1924
}

android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/page/VpnSettingsPage.kt

+6
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,18 @@ class VpnSettingsPage internal constructor() : Page() {
4545
scrollView2.scrollUntil(Direction.DOWN, Until.hasObject(By.res(testTag)))
4646
}
4747

48+
fun clickWireguardCustomPort() {
49+
uiDevice.findObjectWithTimeout(By.res(WIREGUARD_CUSTOM_PORT_CELL_TEST_TAG)).click()
50+
}
51+
4852
companion object {
4953
const val SETTINGS_SCROLL_VIEW_TEST_TAG = "lazy_list_vpn_settings_test_tag"
5054
const val WIREGUARD_OBFUSCATION_UDP_OVER_TCP_CELL_TEST_TAG =
5155
"wireguard_obfuscation_udp_over_tcp_cell_test_tag"
5256
const val WIREGUARD_OBFUSCATION_OFF_CELL_TEST_TAG =
5357
"wireguard_obfuscation_off_cell_test_tag"
58+
const val WIREGUARD_CUSTOM_PORT_CELL_TEST_TAG =
59+
"lazy_list_wireguard_custom_port_text_test_tag"
5460
const val SWITCH_TEST_TAG = "switch_test_tag"
5561
}
5662
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package net.mullvad.mullvadvpn.test.common.page
2+
3+
import androidx.test.uiautomator.By
4+
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
5+
6+
class WireGuardCustomPortDialog internal constructor() : Page() {
7+
private val textFieldLabelSelector = By.text("Enter port")
8+
private val setPortSelector = By.text("Set port")
9+
private val cancelSelector = By.text("Cancel")
10+
11+
override fun assertIsDisplayed() {
12+
uiDevice.findObjectWithTimeout(textFieldLabelSelector)
13+
}
14+
15+
fun enterCustomPort(port: String) {
16+
uiDevice.findObjectWithTimeout(textFieldLabelSelector).parent.text = port
17+
}
18+
19+
fun clickSetPort() {
20+
uiDevice.findObjectWithTimeout(setPortSelector).click()
21+
}
22+
23+
fun clickCancel() {
24+
uiDevice.findObjectWithTimeout(cancelSelector).click()
25+
}
26+
27+
companion object {
28+
const val TEXT_FIELD_TEST_TAG = "custom_port_dialog_input_test_tag"
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
package net.mullvad.mullvadvpn.test.e2e
22

3-
import androidx.test.uiautomator.By
43
import kotlin.time.Duration.Companion.milliseconds
54
import kotlinx.coroutines.delay
65
import kotlinx.coroutines.runBlocking
7-
import net.mullvad.mullvadvpn.compose.test.EXPAND_BUTTON_TEST_TAG
8-
import net.mullvad.mullvadvpn.compose.test.SELECT_LOCATION_BUTTON_TEST_TAG
9-
import net.mullvad.mullvadvpn.compose.test.SWITCH_TEST_TAG
10-
import net.mullvad.mullvadvpn.compose.test.TOP_BAR_SETTINGS_BUTTON
11-
import net.mullvad.mullvadvpn.test.common.constant.VERY_LONG_TIMEOUT
12-
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
136
import net.mullvad.mullvadvpn.test.common.misc.Attachment
7+
import net.mullvad.mullvadvpn.test.common.page.ConnectPage
8+
import net.mullvad.mullvadvpn.test.common.page.SelectLocationPage
9+
import net.mullvad.mullvadvpn.test.common.page.SettingsPage
10+
import net.mullvad.mullvadvpn.test.common.page.SystemVpnConfigurationAlert
11+
import net.mullvad.mullvadvpn.test.common.page.TopBar
12+
import net.mullvad.mullvadvpn.test.common.page.VpnSettingsPage
13+
import net.mullvad.mullvadvpn.test.common.page.WireGuardCustomPortDialog
14+
import net.mullvad.mullvadvpn.test.common.page.on
1415
import net.mullvad.mullvadvpn.test.common.rule.ForgetAllVpnAppsInSettingsTestRule
1516
import net.mullvad.mullvadvpn.test.e2e.annotations.HasDependencyOnLocalAPI
1617
import net.mullvad.mullvadvpn.test.e2e.misc.AccountTestRule
@@ -34,18 +35,22 @@ class LeakTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
3435
@BeforeEach
3536
fun setupVPNSettings() {
3637
app.launchAndEnsureLoggedIn(accountTestRule.validAccountNumber)
37-
device.findObjectWithTimeout(By.res(TOP_BAR_SETTINGS_BUTTON)).click()
38-
device.findObjectWithTimeout(By.text("VPN settings")).click()
3938

40-
val localNetworkSharingCell =
41-
device.findObjectWithTimeout(By.text("Local network sharing")).parent
42-
val localNetworkSharingSwitch =
43-
localNetworkSharingCell.findObjectWithTimeout(By.res(SWITCH_TEST_TAG))
39+
on<TopBar> { clickSettings() }
4440

45-
localNetworkSharingSwitch.click()
41+
on<SettingsPage> { clickVpnSettings() }
4642

47-
// Only use port 51820 to make packet capture more deterministic
48-
device.findObjectWithTimeout(By.text("51820")).click()
43+
on<VpnSettingsPage> {
44+
clickLocalNetworkSharingSwitch()
45+
clickWireguardCustomPort()
46+
}
47+
48+
on<WireGuardCustomPortDialog> {
49+
enterCustomPort("51820")
50+
clickSetPort()
51+
}
52+
53+
on<VpnSettingsPage> {}
4954

5055
device.pressBack()
5156
device.pressBack()
@@ -56,18 +61,26 @@ class LeakTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
5661
fun testNegativeLeak() =
5762
runBlocking<Unit> {
5863
app.launch()
59-
device.findObjectWithTimeout(By.text("DISCONNECTED"))
6064

61-
val targetIpAddress = BuildConfig.TRAFFIC_GENERATION_IP_ADDRESS
62-
val targetPort = 80
65+
on<ConnectPage> {
66+
waitForDisconnectedLabel()
67+
68+
clickSelectLocation()
69+
}
6370

64-
device.findObjectWithTimeout(By.res(SELECT_LOCATION_BUTTON_TEST_TAG)).click()
65-
clickLocationExpandButton(DEFAULT_COUNTRY)
66-
clickLocationExpandButton(DEFAULT_CITY)
67-
device.findObjectWithTimeout(By.text(DEFAULT_RELAY)).click()
68-
device.findObjectWithTimeout(By.text("OK")).click()
69-
device.findObjectWithTimeout(By.text("CONNECTED"), VERY_LONG_TIMEOUT)
71+
on<SelectLocationPage> {
72+
clickLocationExpandButton(DEFAULT_COUNTRY)
73+
clickLocationExpandButton(DEFAULT_CITY)
74+
clickLocationCell(DEFAULT_RELAY)
75+
}
7076

77+
on<SystemVpnConfigurationAlert> { clickOk() }
78+
79+
on<ConnectPage> { waitForConnectedLabel() }
80+
81+
// Capture generated traffic to a specific host
82+
val targetIpAddress = BuildConfig.TRAFFIC_GENERATION_IP_ADDRESS
83+
val targetPort = 80
7184
val captureResult =
7285
PacketCapture().capturePackets {
7386
TrafficGenerator(targetIpAddress, targetPort).generateTraffic(10.milliseconds) {
@@ -76,11 +89,10 @@ class LeakTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
7689
}
7790
}
7891

79-
device.findObjectWithTimeout(By.text("Disconnect")).click()
92+
on<ConnectPage> { clickDisconnect() }
8093

8194
val capturedStreams = captureResult.streams
8295
val capturedPcap = captureResult.pcap
83-
8496
val timestamp = System.currentTimeMillis()
8597
Attachment.saveAttachment("capture-testNegativeLeak-$timestamp.pcap", capturedPcap)
8698

@@ -93,37 +105,51 @@ class LeakTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
93105
fun testShouldHaveNegativeLeak() =
94106
runBlocking<Unit> {
95107
app.launch()
96-
device.findObjectWithTimeout(By.text("DISCONNECTED"))
97108

98-
val targetIpAddress = BuildConfig.TRAFFIC_GENERATION_IP_ADDRESS
99-
val targetPort = 80
109+
on<ConnectPage> {
110+
waitForDisconnectedLabel()
111+
112+
clickSelectLocation()
113+
}
114+
115+
on<SelectLocationPage> {
116+
clickLocationExpandButton(DEFAULT_COUNTRY)
117+
clickLocationExpandButton(DEFAULT_CITY)
118+
clickLocationCell(DEFAULT_RELAY)
119+
}
100120

101-
device.findObjectWithTimeout(By.res(SELECT_LOCATION_BUTTON_TEST_TAG)).click()
102-
delay(1000.milliseconds)
103-
clickLocationExpandButton(DEFAULT_COUNTRY)
104-
clickLocationExpandButton(DEFAULT_CITY)
105-
device.findObjectWithTimeout(By.text(DEFAULT_RELAY)).click()
106-
device.findObjectWithTimeout(By.text("OK")).click()
107-
device.findObjectWithTimeout(By.text("CONNECTED"), VERY_LONG_TIMEOUT)
121+
on<SystemVpnConfigurationAlert> { clickOk() }
108122

123+
on<ConnectPage> { waitForConnectedLabel() }
124+
125+
// Capture generated traffic to a specific host
126+
val targetIpAddress = BuildConfig.TRAFFIC_GENERATION_IP_ADDRESS
127+
val targetPort = 80
109128
val captureResult: PacketCaptureResult =
110129
PacketCapture().capturePackets {
111130
TrafficGenerator(targetIpAddress, targetPort).generateTraffic(10.milliseconds) {
112131
delay(
113132
3000.milliseconds
114133
) // Give it some time for generating traffic in tunnel
115-
device.findObjectWithTimeout(By.text("Disconnect")).click()
134+
135+
on<ConnectPage> { clickDisconnect() }
136+
116137
delay(
117138
2000.milliseconds
118139
) // Give it some time to leak traffic outside of tunnel
119-
device.findObjectWithTimeout(By.text("Connect")).click()
140+
141+
on<ConnectPage> {
142+
clickConnect()
143+
waitForConnectedLabel()
144+
}
145+
120146
delay(
121147
3000.milliseconds
122148
) // Give it some time for generating traffic in tunnel
123149
}
124150
}
125151

126-
device.findObjectWithTimeout(By.text("Disconnect")).click()
152+
on<ConnectPage> { clickDisconnect() }
127153

128154
val capturedStreams = captureResult.streams
129155
val capturedPcap = captureResult.pcap
@@ -133,10 +159,4 @@ class LeakTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
133159
val leakRules = listOf(NoTrafficToHostRule(targetIpAddress))
134160
LeakCheck.assertLeaks(capturedStreams, leakRules)
135161
}
136-
137-
private fun clickLocationExpandButton(locationName: String) {
138-
val locationCell = device.findObjectWithTimeout(By.text(locationName)).parent.parent
139-
val expandButton = locationCell.findObjectWithTimeout(By.res(EXPAND_BUTTON_TEST_TAG))
140-
expandButton.click()
141-
}
142162
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package net.mullvad.mullvadvpn.test.e2e
22

3-
import androidx.test.uiautomator.By
4-
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
3+
import net.mullvad.mullvadvpn.test.common.page.AccountPage
4+
import net.mullvad.mullvadvpn.test.common.page.LoginPage
5+
import net.mullvad.mullvadvpn.test.common.page.TopBar
6+
import net.mullvad.mullvadvpn.test.common.page.on
57
import net.mullvad.mullvadvpn.test.e2e.misc.AccountTestRule
6-
import org.junit.jupiter.api.Assertions.assertNotNull
78
import org.junit.jupiter.api.Test
89
import org.junit.jupiter.api.extension.RegisterExtension
910

@@ -16,11 +17,10 @@ class LogoutTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
1617
// Given
1718
app.launchAndEnsureLoggedIn(accountTestRule.validAccountNumber)
1819

19-
// When
20-
app.clickAccountCog()
21-
app.clickActionButtonByText("Log out")
20+
on<TopBar> { clickAccount() }
2221

23-
// Then
24-
assertNotNull(device.findObjectWithTimeout(By.text("Login")))
22+
on<AccountPage> { clickLogOut() }
23+
24+
on<LoginPage>()
2525
}
2626
}
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,22 @@
11
package net.mullvad.mullvadvpn.test.e2e
22

3-
import androidx.test.uiautomator.By
43
import net.mullvad.mullvadvpn.test.common.annotation.SkipForFlavors
5-
import net.mullvad.mullvadvpn.test.common.constant.VERY_LONG_TIMEOUT
6-
import net.mullvad.mullvadvpn.test.common.extension.clickAgreeOnPrivacyDisclaimer
7-
import net.mullvad.mullvadvpn.test.common.extension.clickAllowOnNotificationPermissionPromptIfApiLevel33AndAbove
8-
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
4+
import net.mullvad.mullvadvpn.test.common.page.MullvadWebsite
5+
import net.mullvad.mullvadvpn.test.common.page.SettingsPage
6+
import net.mullvad.mullvadvpn.test.common.page.TopBar
7+
import net.mullvad.mullvadvpn.test.common.page.on
98
import org.junit.jupiter.api.Test
109

1110
class WebLinkTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
1211
@Test
1312
@SkipForFlavors(currentFlavor = BuildConfig.FLAVOR_billing, "play")
1413
fun testOpenFaqFromApp() {
15-
// Given
16-
app.launch()
14+
app.launchAndEnsureOnLoginPage()
1715

18-
// When
19-
device.clickAgreeOnPrivacyDisclaimer()
20-
device.clickAllowOnNotificationPermissionPromptIfApiLevel33AndAbove()
21-
device.findObjectWithTimeout(By.text("Login"))
22-
app.clickSettingsCog()
23-
app.clickListItemByText("FAQs & Guides")
16+
on<TopBar> { clickSettings() }
2417

25-
// Then
26-
device.findObjectWithTimeout(
27-
selector = By.text("Mullvad help center"),
28-
timeout = VERY_LONG_TIMEOUT,
29-
)
18+
on<SettingsPage> { clickFaqAndGuides() }
19+
20+
on<MullvadWebsite>()
3021
}
3122
}

0 commit comments

Comments
 (0)