diff options
| author | Albin <albin@mullvad.net> | 2023-03-22 16:15:30 +0100 |
|---|---|---|
| committer | Albin <albin@mullvad.net> | 2023-03-22 17:15:58 +0100 |
| commit | 128d188883d878dd84d3ace6dbbc6e553702a347 (patch) | |
| tree | ee30deb2e070db6a555da56a21fed829e77895b9 /android | |
| parent | d97365cb916ed05ee07f2defb901db31918fe580 (diff) | |
| download | mullvadvpn-128d188883d878dd84d3ace6dbbc6e553702a347.tar.xz mullvadvpn-128d188883d878dd84d3ace6dbbc6e553702a347.zip | |
Add advanced settings ui tests
Diffstat (limited to 'android')
| -rw-r--r-- | android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingsScreenTest.kt | 552 |
1 files changed, 552 insertions, 0 deletions
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingsScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingsScreenTest.kt new file mode 100644 index 0000000000..1aaf119773 --- /dev/null +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingsScreenTest.kt @@ -0,0 +1,552 @@ +package net.mullvad.mullvadvpn.compose.screen + +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.ui.test.assertIsEnabled +import androidx.compose.ui.test.assertIsNotEnabled +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performTextInput +import io.mockk.MockKAnnotations +import io.mockk.mockk +import io.mockk.verify +import io.mockk.verifyAll +import net.mullvad.mullvadvpn.compose.state.AdvancedSettingsUiState +import net.mullvad.mullvadvpn.viewmodel.CustomDnsItem +import net.mullvad.mullvadvpn.viewmodel.StagedDns +import org.junit.Before +import org.junit.Rule +import org.junit.Test + +class AdvancedSettingsScreenTest { + @get:Rule val composeTestRule = createComposeRule() + + @Before + fun setup() { + MockKAnnotations.init(this) + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testDefaultState() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen(uiState = AdvancedSettingsUiState.DefaultUiState()) + } + + // Assert + composeTestRule.apply { + onNodeWithText("WireGuard MTU").assertExists() + onNodeWithText("Default").assertExists() + onNodeWithText("Split tunneling").assertExists() + onNodeWithText("Use custom DNS server").assertExists() + onNodeWithText("Add a server").assertDoesNotExist() + } + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testMtuCustomValue() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = AdvancedSettingsUiState.DefaultUiState(mtu = VALID_DUMMY_MTU_VALUE) + ) + } + + // Assert + composeTestRule.onNodeWithText(VALID_DUMMY_MTU_VALUE).assertExists() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testMtuClick() { + // Arrange + val mockedClickHandler: () -> Unit = mockk(relaxed = true) + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = AdvancedSettingsUiState.DefaultUiState(), + onMtuCellClick = mockedClickHandler + ) + } + + // Act + composeTestRule.onNodeWithText("WireGuard MTU").performClick() + + // Assert + verify { mockedClickHandler.invoke() } + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testMtuDialogWithDefaultValue() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = AdvancedSettingsUiState.MtuDialogUiState(mtuEditValue = EMPTY_STRING) + ) + } + + // Assert + composeTestRule.onNodeWithText(EMPTY_STRING).assertExists() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testMtuDialogWithEditValue() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.MtuDialogUiState(mtuEditValue = VALID_DUMMY_MTU_VALUE) + ) + } + + // Assert + composeTestRule.onNodeWithText(VALID_DUMMY_MTU_VALUE).assertExists() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testMtuDialogTextInput() { + // Arrange + val mockedInputHandler: (String) -> Unit = mockk(relaxed = true) + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = AdvancedSettingsUiState.MtuDialogUiState(mtuEditValue = EMPTY_STRING), + onMtuInputChange = mockedInputHandler + ) + } + + // Act + composeTestRule.onNodeWithText(EMPTY_STRING).performTextInput(VALID_DUMMY_MTU_VALUE) + + // Assert + verifyAll { mockedInputHandler.invoke(VALID_DUMMY_MTU_VALUE) } + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testMtuDialogSubmitOfValidValue() { + // Arrange + val mockedSubmitHandler: () -> Unit = mockk(relaxed = true) + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.MtuDialogUiState(mtuEditValue = VALID_DUMMY_MTU_VALUE), + onSaveMtuClick = mockedSubmitHandler + ) + } + + // Act + composeTestRule.onNodeWithText("Submit").assertIsEnabled().performClick() + + // Assert + verify { mockedSubmitHandler.invoke() } + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testMtuDialogSubmitButtonDisabledWhenInvalidInput() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.MtuDialogUiState(mtuEditValue = INVALID_DUMMY_MTU_VALUE) + ) + } + + // Assert + composeTestRule.onNodeWithText("Submit").assertIsNotEnabled() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testMtuDialogResetClick() { + // Arrange + val mockedClickHandler: () -> Unit = mockk(relaxed = true) + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = AdvancedSettingsUiState.MtuDialogUiState(mtuEditValue = EMPTY_STRING), + onRestoreMtuClick = mockedClickHandler + ) + } + + // Act + composeTestRule.onNodeWithText("Reset to default").performClick() + + // Assert + verify { mockedClickHandler.invoke() } + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testMtuDialogCancelClick() { + // Arrange + val mockedClickHandler: () -> Unit = mockk(relaxed = true) + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = AdvancedSettingsUiState.MtuDialogUiState(mtuEditValue = EMPTY_STRING), + onCancelMtuDialogClicked = mockedClickHandler + ) + } + + // Assert + composeTestRule.onNodeWithText("Cancel").performClick() + + // Assert + verify { mockedClickHandler.invoke() } + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testClickSplitTunneling() { + // Arrange + val mockedClickHandler: () -> Unit = mockk(relaxed = true) + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = AdvancedSettingsUiState.DefaultUiState(), + onSplitTunnelingNavigationClick = mockedClickHandler + ) + } + + // Act + composeTestRule.onNodeWithText("Split tunneling").performClick() + + // Assert + verify { mockedClickHandler.invoke() } + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testCustomDnsAddressesAndAddButtonVisibleWhenCustomDnsEnabled() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DefaultUiState( + isCustomDnsEnabled = true, + isAllowLanEnabled = false, + customDnsItems = + listOf( + CustomDnsItem(address = DUMMY_DNS_ADDRESS, false), + CustomDnsItem(address = DUMMY_DNS_ADDRESS_2, false), + CustomDnsItem(address = DUMMY_DNS_ADDRESS_3, false) + ) + ) + ) + } + + // Assert + composeTestRule.apply { + onNodeWithText(DUMMY_DNS_ADDRESS).assertExists() + onNodeWithText(DUMMY_DNS_ADDRESS_2).assertExists() + onNodeWithText(DUMMY_DNS_ADDRESS_3).assertExists() + onNodeWithText("Add a server").assertExists() + } + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testCustomDnsAddressesAndAddButtonNotVisibleWhenCustomDnsDisabled() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DefaultUiState( + isCustomDnsEnabled = false, + customDnsItems = listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, false)) + ) + ) + } + + // Assert + composeTestRule.onNodeWithText(DUMMY_DNS_ADDRESS).assertDoesNotExist() + composeTestRule.onNodeWithText("Add a server").assertDoesNotExist() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testLanWarningNotShownWhenLanTrafficEnabledAndLocalAddressIsUsed() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DefaultUiState( + isCustomDnsEnabled = true, + isAllowLanEnabled = true, + customDnsItems = + listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = true)) + ) + ) + } + + // Assert + composeTestRule.onNodeWithContentDescription(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testLanWarningNotShowedWhenLanTrafficDisabledAndLocalAddressIsNotUsed() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DefaultUiState( + isCustomDnsEnabled = true, + isAllowLanEnabled = false, + customDnsItems = + listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = false)) + ) + ) + } + + // Assert + composeTestRule.onNodeWithContentDescription(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testLanWarningNotShowedWhenLanTrafficEnabledAndLocalAddressIsNotUsed() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DefaultUiState( + isCustomDnsEnabled = true, + isAllowLanEnabled = true, + customDnsItems = + listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = false)) + ) + ) + } + + // Assert + composeTestRule.onNodeWithContentDescription(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testLanWarningShowedWhenAllowLanEnabledAndLocalDnsAddressIsUsed() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DefaultUiState( + isCustomDnsEnabled = true, + isAllowLanEnabled = false, + customDnsItems = + listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = true)) + ) + ) + } + + // Assert + composeTestRule.apply { + onNodeWithContentDescription(LOCAL_DNS_SERVER_WARNING).assertExists() + } + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testClickAddDns() { + // Arrange + val mockedClickHandler: (Int?) -> Unit = mockk(relaxed = true) + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = AdvancedSettingsUiState.DefaultUiState(isCustomDnsEnabled = true), + onDnsClick = mockedClickHandler + ) + } + + // Act + composeTestRule.onNodeWithText("Add a server").performClick() + + // Assert + verify { mockedClickHandler.invoke(null) } + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testShowDnsDialogForNewDnsServer() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DnsDialogUiState( + stagedDns = + StagedDns.NewDns( + item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false) + ) + ) + ) + } + + // Assert + composeTestRule.onNodeWithText("Add DNS server").assertExists() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testShowDnsDialogForUpdatingDnsServer() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DnsDialogUiState( + stagedDns = + StagedDns.EditDns( + item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false), + index = 0 + ) + ) + ) + } + + // Assert + composeTestRule.onNodeWithText("Update DNS server").assertExists() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testDnsDialogLanWarningShownWhenLanTrafficDisabledAndLocalAddressUsed() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DnsDialogUiState( + stagedDns = + StagedDns.NewDns( + item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = true), + validationResult = StagedDns.ValidationResult.Success + ), + isAllowLanEnabled = false + ) + ) + } + + // Assert + composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertExists() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testDnsDialogLanWarningNotShownWhenLanTrafficEnabledAndLocalAddressUsed() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DnsDialogUiState( + stagedDns = + StagedDns.NewDns( + item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = true), + validationResult = StagedDns.ValidationResult.Success + ), + isAllowLanEnabled = true + ) + ) + } + + // Assert + composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testDnsDialogLanWarningNotShownWhenLanTrafficEnabledAndNonLocalAddressUsed() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DnsDialogUiState( + stagedDns = + StagedDns.NewDns( + item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false), + validationResult = StagedDns.ValidationResult.Success + ), + isAllowLanEnabled = true + ) + ) + } + + // Assert + composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testDnsDialogLanWarningNotShownWhenLanTrafficDisabledAndNonLocalAddressUsed() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DnsDialogUiState( + stagedDns = + StagedDns.NewDns( + item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false), + validationResult = StagedDns.ValidationResult.Success + ), + isAllowLanEnabled = false + ) + ) + } + + // Assert + composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testDnsDialogSubmitButtonDisabledOnInvalidDnsAddress() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DnsDialogUiState( + stagedDns = + StagedDns.NewDns( + item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false), + validationResult = StagedDns.ValidationResult.InvalidAddress + ) + ) + ) + } + + // Assert + composeTestRule.onNodeWithText("Submit").assertIsNotEnabled() + } + + @Test + @OptIn(ExperimentalMaterialApi::class) + fun testDnsDialogSubmitButtonDisabledOnDuplicateDnsAddress() { + // Arrange + composeTestRule.setContent { + AdvancedSettingScreen( + uiState = + AdvancedSettingsUiState.DnsDialogUiState( + stagedDns = + StagedDns.NewDns( + item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false), + validationResult = StagedDns.ValidationResult.DuplicateAddress + ) + ) + ) + } + + // Assert + composeTestRule.onNodeWithText("Submit").assertIsNotEnabled() + } + + companion object { + private const val LOCAL_DNS_SERVER_WARNING = + "The local DNS server will not work unless you enable " + + "\"Local Network Sharing\" under Preferences." + private const val EMPTY_STRING = "" + private const val VALID_DUMMY_MTU_VALUE = "1337" + private const val INVALID_DUMMY_MTU_VALUE = "1111" + private const val DUMMY_DNS_ADDRESS = "0.0.0.1" + private const val DUMMY_DNS_ADDRESS_2 = "0.0.0.2" + private const val DUMMY_DNS_ADDRESS_3 = "0.0.0.3" + } +} |
