diff options
| author | David Göransson <david.goransson@mullvad.net> | 2025-03-31 09:36:52 +0200 |
|---|---|---|
| committer | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2025-04-10 17:29:33 +0200 |
| commit | 042820a80d994a09a58dfcdc7dce1ee1d891ac39 (patch) | |
| tree | b35efcceebded11d98cec4adc08a52febb2eedf8 /android/app/src/androidTest | |
| parent | 1c5712f028250920fe34ce7686c77a7d80da9481 (diff) | |
| download | mullvadvpn-042820a80d994a09a58dfcdc7dce1ee1d891ac39.tar.xz mullvadvpn-042820a80d994a09a58dfcdc7dce1ee1d891ac39.zip | |
Implement quick access to active features
- Add Daita: Multihop feature indicator
- Make feature indicators clickable
- Add animations when accessing the features through the indicators
- Rework VpnSettings in order to support navigating to a feature in the
list
Diffstat (limited to 'android/app/src/androidTest')
2 files changed, 133 insertions, 49 deletions
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt index 4b5ea29fd6..8fefd1e33d 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt @@ -25,6 +25,7 @@ import net.mullvad.mullvadvpn.compose.test.TOP_BAR_ACCOUNT_BUTTON import net.mullvad.mullvadvpn.lib.model.ActionAfterDisconnect import net.mullvad.mullvadvpn.lib.model.ErrorState import net.mullvad.mullvadvpn.lib.model.ErrorStateCause +import net.mullvad.mullvadvpn.lib.model.FeatureIndicator import net.mullvad.mullvadvpn.lib.model.GeoIpLocation import net.mullvad.mullvadvpn.lib.model.InAppNotification import net.mullvad.mullvadvpn.lib.model.TransportProtocol @@ -70,6 +71,7 @@ class ConnectScreenTest { onDismissNewDeviceClick: () -> Unit = {}, onChangelogClick: () -> Unit = {}, onDismissChangelogClick: () -> Unit = {}, + onNavigateToFeature: (FeatureIndicator) -> Unit = {}, ) { setContentWithTheme { ConnectScreen( @@ -86,6 +88,7 @@ class ConnectScreenTest { onDismissNewDeviceClick = onDismissNewDeviceClick, onChangelogClick = onChangelogClick, onDismissChangelogClick = onDismissChangelogClick, + onNavigateToFeature = onNavigateToFeature, ) } } @@ -801,4 +804,47 @@ class ConnectScreenTest { onNodeWithText(outIpv6).assertExists() } } + + @Test + fun clickOnFeatureIndicator() { + composeExtension.use { + // Arrange + val mockLocation: GeoIpLocation = mockk(relaxed = true) + val mockTunnelEndpoint: TunnelEndpoint = mockk(relaxed = true) + val mockHostName = "Host-Name" + every { mockLocation.hostname } returns mockHostName + every { mockLocation.entryHostname } returns null + + // In + every { mockTunnelEndpoint.obfuscation } returns null + + val mockClickHandler = mockk<(FeatureIndicator) -> Unit>(relaxed = true) + + initScreen( + state = + ConnectUiState( + location = mockLocation, + selectedRelayItemTitle = null, + tunnelState = + TunnelState.Connected( + mockTunnelEndpoint, + mockLocation, + listOf(FeatureIndicator.MULTIHOP), + ), + showLocation = false, + deviceName = "", + daysLeftUntilExpiry = null, + inAppNotification = null, + isPlayBuild = false, + ), + onNavigateToFeature = mockClickHandler, + ) + + // Act + onNodeWithText("Multihop").performClick() + + // Assert + verify(exactly = 1) { mockClickHandler.invoke(FeatureIndicator.MULTIHOP) } + } + } } diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt index 963762c246..0eda50c8e6 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt @@ -13,7 +13,6 @@ import io.mockk.mockk import io.mockk.verify import net.mullvad.mullvadvpn.compose.createEdgeToEdgeComposeExtension import net.mullvad.mullvadvpn.compose.setContentWithTheme -import net.mullvad.mullvadvpn.compose.state.VpnSettingsUiState import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_LAST_ITEM_TEST_TAG import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_QUANTUM_ITEM_OFF_TEST_TAG import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_QUANTUM_ITEM_ON_TEST_TAG @@ -23,6 +22,7 @@ import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_ import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_WIREGUARD_OBFUSCATION_TITLE_TEST_TAG import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG import net.mullvad.mullvadvpn.lib.model.Constraint +import net.mullvad.mullvadvpn.lib.model.DefaultDnsOptions import net.mullvad.mullvadvpn.lib.model.IpVersion import net.mullvad.mullvadvpn.lib.model.Mtu import net.mullvad.mullvadvpn.lib.model.ObfuscationMode @@ -31,6 +31,7 @@ import net.mullvad.mullvadvpn.lib.model.PortRange import net.mullvad.mullvadvpn.lib.model.QuantumResistantState import net.mullvad.mullvadvpn.onNodeWithTagAndText import net.mullvad.mullvadvpn.viewmodel.CustomDnsItem +import net.mullvad.mullvadvpn.viewmodel.VpnSettingsUiState import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.RegisterExtension @@ -44,8 +45,49 @@ class VpnSettingsScreenTest { MockKAnnotations.init(this) } + private fun createDefaultUiState( + mtu: Mtu? = null, + isLocalNetworkSharingEnabled: Boolean = false, + isCustomDnsEnabled: Boolean = false, + customDnsItems: List<CustomDnsItem> = emptyList(), + contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(), + obfuscationMode: ObfuscationMode = ObfuscationMode.Auto, + selectedUdp2TcpObfuscationPort: Constraint<Port> = Constraint.Any, + selectedShadowsocksObfuscationPort: Constraint<Port> = Constraint.Any, + quantumResistant: QuantumResistantState = QuantumResistantState.Auto, + selectedWireguardPort: Constraint<Port> = Constraint.Any, + customWireguardPort: Port? = null, + availablePortRanges: List<PortRange> = emptyList(), + systemVpnSettingsAvailable: Boolean = true, + autoStartAndConnectOnBoot: Boolean = false, + deviceIpVersion: Constraint<IpVersion> = Constraint.Any, + isIpv6Enabled: Boolean = true, + isContentBlockersExpanded: Boolean = false, + isModal: Boolean = false, + ) = + VpnSettingsUiState.Content.from( + mtu = mtu, + isLocalNetworkSharingEnabled = isLocalNetworkSharingEnabled, + isCustomDnsEnabled = isCustomDnsEnabled, + customDnsItems = customDnsItems, + contentBlockersOptions = contentBlockersOptions, + obfuscationMode = obfuscationMode, + selectedUdp2TcpObfuscationPort = selectedUdp2TcpObfuscationPort, + selectedShadowsocksObfuscationPort = selectedShadowsocksObfuscationPort, + quantumResistant = quantumResistant, + selectedWireguardPort = selectedWireguardPort, + customWireguardPort = customWireguardPort, + availablePortRanges = availablePortRanges, + systemVpnSettingsAvailable = systemVpnSettingsAvailable, + autoStartAndConnectOnBoot = autoStartAndConnectOnBoot, + deviceIpVersion = deviceIpVersion, + isIpv6Enabled = isIpv6Enabled, + isContentBlockersExpanded = isContentBlockersExpanded, + isModal = isModal, + ) + private fun ComposeContext.initScreen( - state: VpnSettingsUiState = VpnSettingsUiState.createDefault(), + state: VpnSettingsUiState = createDefaultUiState(), navigateToContentBlockersInfo: () -> Unit = {}, navigateToAutoConnectScreen: () -> Unit = {}, navigateToCustomDnsInfo: () -> Unit = {}, @@ -54,7 +96,7 @@ class VpnSettingsScreenTest { navigateToQuantumResistanceInfo: () -> Unit = {}, navigateToWireguardPortInfo: (availablePortRanges: List<PortRange>) -> Unit = {}, navigateToLocalNetworkSharingInfo: () -> Unit = {}, - navigateToWireguardPortDialog: () -> Unit = {}, + navigateToWireguardPortDialog: (Port?, List<PortRange>) -> Unit = { _, _ -> }, navigateToServerIpOverrides: () -> Unit = {}, onToggleBlockTrackers: (Boolean) -> Unit = {}, onToggleBlockAds: (Boolean) -> Unit = {}, @@ -76,6 +118,7 @@ class VpnSettingsScreenTest { onSelectDeviceIpVersion: (Constraint<IpVersion>) -> Unit = {}, onToggleIpv6: (Boolean) -> Unit = {}, navigateToIpv6Info: () -> Unit = {}, + onToggleDnsContentBlockers: () -> Unit = {}, navigateToDeviceIpInfo: () -> Unit = {}, ) { setContentWithTheme { @@ -111,7 +154,9 @@ class VpnSettingsScreenTest { onSelectDeviceIpVersion = onSelectDeviceIpVersion, onToggleIpv6 = onToggleIpv6, navigateToIpv6Info = navigateToIpv6Info, + onToggleContentBlockersExpanded = onToggleDnsContentBlockers, navigateToDeviceIpInfo = navigateToDeviceIpInfo, + initialScrollToFeature = null, ) } } @@ -120,7 +165,7 @@ class VpnSettingsScreenTest { fun testDefaultState() = composeExtension.use { // Arrange - initScreen(state = VpnSettingsUiState.createDefault()) + initScreen() onNodeWithTag(LAZY_LIST_VPN_SETTINGS_TEST_TAG) .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG)) @@ -138,9 +183,7 @@ class VpnSettingsScreenTest { // Arrange initScreen( state = - VpnSettingsUiState.createDefault( - mtu = Mtu.fromString(VALID_DUMMY_MTU_VALUE).getOrNull()!! - ) + createDefaultUiState(mtu = Mtu.fromString(VALID_DUMMY_MTU_VALUE).getOrNull()!!) ) onNodeWithTag(LAZY_LIST_VPN_SETTINGS_TEST_TAG) @@ -156,7 +199,7 @@ class VpnSettingsScreenTest { // Arrange initScreen( state = - VpnSettingsUiState.createDefault( + createDefaultUiState( isCustomDnsEnabled = true, customDnsItems = listOf( @@ -180,7 +223,7 @@ class VpnSettingsScreenTest { // Arrange initScreen( state = - VpnSettingsUiState.createDefault( + createDefaultUiState( isCustomDnsEnabled = false, customDnsItems = listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, false, false)), @@ -199,7 +242,7 @@ class VpnSettingsScreenTest { // Arrange initScreen( state = - VpnSettingsUiState.createDefault( + createDefaultUiState( isCustomDnsEnabled = true, isLocalNetworkSharingEnabled = true, customDnsItems = @@ -223,7 +266,7 @@ class VpnSettingsScreenTest { // Arrange initScreen( state = - VpnSettingsUiState.createDefault( + createDefaultUiState( isCustomDnsEnabled = true, customDnsItems = listOf( @@ -246,7 +289,7 @@ class VpnSettingsScreenTest { // Arrange initScreen( state = - VpnSettingsUiState.createDefault( + createDefaultUiState( isCustomDnsEnabled = true, customDnsItems = listOf( @@ -269,7 +312,7 @@ class VpnSettingsScreenTest { // Arrange initScreen( state = - VpnSettingsUiState.createDefault( + createDefaultUiState( isCustomDnsEnabled = true, customDnsItems = listOf( @@ -290,10 +333,7 @@ class VpnSettingsScreenTest { fun testShowSelectedTunnelQuantumOption() = composeExtension.use { // Arrange - initScreen( - state = - VpnSettingsUiState.createDefault(quantumResistant = QuantumResistantState.On) - ) + initScreen(state = createDefaultUiState(quantumResistant = QuantumResistantState.On)) onNodeWithTag(LAZY_LIST_VPN_SETTINGS_TEST_TAG) .performScrollToNode(hasTestTag(LAZY_LIST_QUANTUM_ITEM_OFF_TEST_TAG)) @@ -309,8 +349,7 @@ class VpnSettingsScreenTest { val mockSelectQuantumResistantSettingListener: (QuantumResistantState) -> Unit = mockk(relaxed = true) initScreen( - state = - VpnSettingsUiState.createDefault(quantumResistant = QuantumResistantState.Auto), + state = createDefaultUiState(quantumResistant = QuantumResistantState.Auto), onSelectQuantumResistanceSetting = mockSelectQuantumResistantSettingListener, ) onNodeWithTag(LAZY_LIST_VPN_SETTINGS_TEST_TAG) @@ -329,10 +368,7 @@ class VpnSettingsScreenTest { composeExtension.use { // Arrange initScreen( - state = - VpnSettingsUiState.createDefault( - selectedWireguardPort = Constraint.Only(Port(53)) - ) + state = createDefaultUiState(selectedWireguardPort = Constraint.Only(Port(53))) ) // Act @@ -356,10 +392,7 @@ class VpnSettingsScreenTest { val mockSelectWireguardPortSelectionListener: (Constraint<Port>) -> Unit = mockk(relaxed = true) initScreen( - state = - VpnSettingsUiState.createDefault( - selectedWireguardPort = Constraint.Only(Port(53)) - ), + state = createDefaultUiState(selectedWireguardPort = Constraint.Only(Port(53))), onWireguardPortSelected = mockSelectWireguardPortSelectionListener, ) @@ -384,7 +417,7 @@ class VpnSettingsScreenTest { fun testShowWireguardCustomPort() = composeExtension.use { // Arrange - initScreen(state = VpnSettingsUiState.createDefault(customWireguardPort = Port(4000))) + initScreen(state = createDefaultUiState(customWireguardPort = Port(4000))) // Act onNodeWithTag(LAZY_LIST_VPN_SETTINGS_TEST_TAG) @@ -401,7 +434,7 @@ class VpnSettingsScreenTest { val onWireguardPortSelected: (Constraint<Port>) -> Unit = mockk(relaxed = true) initScreen( state = - VpnSettingsUiState.createDefault( + createDefaultUiState( selectedWireguardPort = Constraint.Only(Port(4000)), customWireguardPort = Port(4000), ), @@ -424,10 +457,7 @@ class VpnSettingsScreenTest { composeExtension.use { // Arrange val mockedClickHandler: (Mtu?) -> Unit = mockk(relaxed = true) - initScreen( - state = VpnSettingsUiState.createDefault(), - navigateToMtuDialog = mockedClickHandler, - ) + initScreen(state = createDefaultUiState(), navigateToMtuDialog = mockedClickHandler) onNodeWithTag(LAZY_LIST_VPN_SETTINGS_TEST_TAG) .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG)) @@ -446,7 +476,7 @@ class VpnSettingsScreenTest { val mockedClickHandler: (Int?, String?) -> Unit = mockk(relaxed = true) initScreen( state = - VpnSettingsUiState.createDefault( + createDefaultUiState( isCustomDnsEnabled = true, customDnsItems = listOf(CustomDnsItem("1.1.1.1", false, false)), ), @@ -467,7 +497,7 @@ class VpnSettingsScreenTest { // Arrange initScreen( - state = VpnSettingsUiState.createDefault(), + state = createDefaultUiState(), navigateToObfuscationInfo = mockedNavigateToObfuscationInfo, ) @@ -487,7 +517,7 @@ class VpnSettingsScreenTest { // Arrange initScreen( - state = VpnSettingsUiState.createDefault(), + state = createDefaultUiState(), navigateToQuantumResistanceInfo = mockedShowTunnelQuantumInfoClick, ) @@ -507,7 +537,7 @@ class VpnSettingsScreenTest { // Arrange initScreen( - state = VpnSettingsUiState.createDefault(), + state = createDefaultUiState(), navigateToWireguardPortInfo = mockedClickHandler, ) @@ -519,11 +549,13 @@ class VpnSettingsScreenTest { @Test fun testShowWireguardCustomPortDialog() = composeExtension.use { - val mockedClickHandler: () -> Unit = mockk(relaxed = true) + val mockedClickHandler: (Port?, List<PortRange>) -> Unit = mockk(relaxed = true) + + val availablePortRanges = listOf(Port(4000)..Port(5000)) // Arrange initScreen( - state = VpnSettingsUiState.createDefault(), + state = createDefaultUiState(availablePortRanges = availablePortRanges), navigateToWireguardPortDialog = mockedClickHandler, ) @@ -532,16 +564,17 @@ class VpnSettingsScreenTest { onNodeWithText("Custom").performClick() // Assert - verify(exactly = 1) { mockedClickHandler.invoke() } + verify(exactly = 1) { mockedClickHandler.invoke(null, availablePortRanges) } } @Test fun testClickWireguardCustomPortMainCell() = composeExtension.use { // Arrange - val mockOnShowCustomPortDialog: () -> Unit = mockk(relaxed = true) + val mockOnShowCustomPortDialog: (Port?, List<PortRange>) -> Unit = mockk(relaxed = true) + val availablePortRanges = listOf(Port(4000)..Port(5000)) initScreen( - state = VpnSettingsUiState.createDefault(), + state = createDefaultUiState(availablePortRanges = availablePortRanges), navigateToWireguardPortDialog = mockOnShowCustomPortDialog, ) @@ -551,18 +584,23 @@ class VpnSettingsScreenTest { onNodeWithTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG).performClick() // Assert - verify { mockOnShowCustomPortDialog.invoke() } + verify { mockOnShowCustomPortDialog.invoke(null, availablePortRanges) } } @Test fun testClickWireguardCustomPortNumberCell() = composeExtension.use { // Arrange - val mockOnShowCustomPortDialog: () -> Unit = mockk(relaxed = true) + val mockOnShowCustomPortDialog: (port: Port?, range: List<PortRange>) -> Unit = + mockk(relaxed = true) + val customPort = Port(4000) + val availablePortRanges = listOf(Port(4000)..Port(5000)) initScreen( state = - VpnSettingsUiState.createDefault( - selectedWireguardPort = Constraint.Only(Port(4000)) + createDefaultUiState( + selectedWireguardPort = Constraint.Only(customPort), + customWireguardPort = customPort, + availablePortRanges = availablePortRanges, ), navigateToWireguardPortDialog = mockOnShowCustomPortDialog, ) @@ -573,14 +611,14 @@ class VpnSettingsScreenTest { onNodeWithTag(testTag = LAZY_LIST_WIREGUARD_CUSTOM_PORT_NUMBER_TEST_TAG).performClick() // Assert - verify { mockOnShowCustomPortDialog.invoke() } + verify { mockOnShowCustomPortDialog.invoke(customPort, availablePortRanges) } } @Test fun ensureConnectOnStartIsShownWhenSystemVpnSettingsAvailableIsFalse() = composeExtension.use { // Arrange - initScreen(state = VpnSettingsUiState.createDefault(systemVpnSettingsAvailable = false)) + initScreen(state = createDefaultUiState(systemVpnSettingsAvailable = false)) // Assert onNodeWithText("Connect on device start-up").assertExists() @@ -593,7 +631,7 @@ class VpnSettingsScreenTest { val mockOnToggleAutoStartAndConnectOnBoot: (Boolean) -> Unit = mockk(relaxed = true) initScreen( state = - VpnSettingsUiState.createDefault( + createDefaultUiState( systemVpnSettingsAvailable = false, autoStartAndConnectOnBoot = false, ), |
