diff options
Diffstat (limited to 'android/app/src/androidTest')
14 files changed, 608 insertions, 1040 deletions
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/CustomPortDialogTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/CustomPortDialogTest.kt new file mode 100644 index 0000000000..43e385b65d --- /dev/null +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/CustomPortDialogTest.kt @@ -0,0 +1,64 @@ +package net.mullvad.mullvadvpn.compose.dialog + +import android.annotation.SuppressLint +import androidx.compose.runtime.Composable +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.performTextInput +import io.mockk.MockKAnnotations +import net.mullvad.mullvadvpn.compose.setContentWithTheme +import net.mullvad.mullvadvpn.compose.test.CUSTOM_PORT_DIALOG_INPUT_TEST_TAG +import net.mullvad.mullvadvpn.model.PortRange +import net.mullvad.mullvadvpn.onNodeWithTagAndText +import org.junit.Before +import org.junit.Rule +import org.junit.Test + +class CustomPortDialogTest { + @get:Rule val composeTestRule = createComposeRule() + + @Before + fun setup() { + MockKAnnotations.init(this) + } + + @SuppressLint("ComposableNaming") + @Composable + private fun testWireguardCustomPortDialog( + initialPort: Int? = null, + allowedPortRanges: List<PortRange> = emptyList(), + onSave: (Int?) -> Unit = { _ -> }, + onDismiss: () -> Unit = {}, + ) { + + WireguardCustomPortDialog( + initialPort = initialPort, + allowedPortRanges = allowedPortRanges, + onSave = onSave, + onDismiss = onDismiss + ) + } + + @Test + fun testShowWireguardCustomPortDialogInvalidInt() { + // Input a number to make sure that a too long number does not show and it does not crash + // the app + + // Arrange + composeTestRule.setContentWithTheme { testWireguardCustomPortDialog() } + + // Act + composeTestRule + .onNodeWithTag(CUSTOM_PORT_DIALOG_INPUT_TEST_TAG) + .performTextInput(invalidCustomPort) + + // Assert + composeTestRule + .onNodeWithTagAndText(CUSTOM_PORT_DIALOG_INPUT_TEST_TAG, invalidCustomPort) + .assertDoesNotExist() + } + + companion object { + const val invalidCustomPort = "21474836471" + } +} diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialogTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialogTest.kt new file mode 100644 index 0000000000..bc8d87b244 --- /dev/null +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialogTest.kt @@ -0,0 +1,120 @@ +package net.mullvad.mullvadvpn.compose.dialog + +import android.annotation.SuppressLint +import androidx.compose.runtime.Composable +import androidx.compose.ui.test.assertIsNotEnabled +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import net.mullvad.mullvadvpn.compose.setContentWithTheme +import net.mullvad.mullvadvpn.viewmodel.DnsDialogViewState +import org.junit.Rule +import org.junit.Test + +class DnsDialogTest { + @get:Rule val composeTestRule = createComposeRule() + + private val defaultState = + DnsDialogViewState( + ipAddress = "", + validationResult = DnsDialogViewState.ValidationResult.Success, + isLocal = false, + isAllowLanEnabled = false, + isNewEntry = true + ) + + @SuppressLint("ComposableNaming") + @Composable + private fun testDnsDialog( + state: DnsDialogViewState = defaultState, + onDnsInputChange: (String) -> Unit = { _ -> }, + onSaveDnsClick: () -> Unit = {}, + onRemoveDnsClick: () -> Unit = {}, + onDismiss: () -> Unit = {} + ) { + DnsDialog(state, onDnsInputChange, onSaveDnsClick, onRemoveDnsClick, onDismiss) + } + + @Test + fun testDnsDialogLanWarningShownWhenLanTrafficDisabledAndLocalAddressUsed() { + // Arrange + composeTestRule.setContentWithTheme { + testDnsDialog(defaultState.copy(isAllowLanEnabled = false, isLocal = true)) + } + + // Assert + composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertExists() + } + + @Test + fun testDnsDialogLanWarningNotShownWhenLanTrafficEnabledAndLocalAddressUsed() { + // Arrange + composeTestRule.setContentWithTheme { + testDnsDialog(defaultState.copy(isAllowLanEnabled = true, isLocal = true)) + } + + // Assert + composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist() + } + + @Test + fun testDnsDialogLanWarningNotShownWhenLanTrafficEnabledAndNonLocalAddressUsed() { + // Arrange + composeTestRule.setContentWithTheme { + testDnsDialog(defaultState.copy(isAllowLanEnabled = true, isLocal = false)) + } + + // Assert + composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist() + } + + @Test + fun testDnsDialogLanWarningNotShownWhenLanTrafficDisabledAndNonLocalAddressUsed() { + // Arrange + composeTestRule.setContentWithTheme { + testDnsDialog(defaultState.copy(isAllowLanEnabled = false, isLocal = false)) + } + + // Assert + composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist() + } + + @Test + fun testDnsDialogSubmitButtonDisabledOnInvalidDnsAddress() { + // Arrange + composeTestRule.setContentWithTheme { + testDnsDialog( + defaultState.copy( + ipAddress = invalidIpAddress, + validationResult = DnsDialogViewState.ValidationResult.InvalidAddress, + ) + ) + } + + // Assert + composeTestRule.onNodeWithText("Submit").assertIsNotEnabled() + } + + @Test + fun testDnsDialogSubmitButtonDisabledOnDuplicateDnsAddress() { + // Arrange + composeTestRule.setContentWithTheme { + testDnsDialog( + defaultState.copy( + ipAddress = "192.168.0.1", + validationResult = DnsDialogViewState.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 invalidIpAddress = "300.300.300.300" + } +} diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialogTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialogTest.kt new file mode 100644 index 0000000000..38a3bd170d --- /dev/null +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialogTest.kt @@ -0,0 +1,153 @@ +package net.mullvad.mullvadvpn.compose.dialog + +import android.annotation.SuppressLint +import androidx.compose.runtime.Composable +import androidx.compose.ui.test.assertIsEnabled +import androidx.compose.ui.test.assertIsNotEnabled +import androidx.compose.ui.test.junit4.createComposeRule +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 net.mullvad.mullvadvpn.compose.setContentWithTheme +import org.junit.Before +import org.junit.Rule +import org.junit.Test + +class MtuDialogTest { + @get:Rule val composeTestRule = createComposeRule() + + @Before + fun setup() { + MockKAnnotations.init(this) + } + + @SuppressLint("ComposableNaming") + @Composable + private fun testMtuDialog( + mtuInitial: Int? = null, + onSaveMtu: (Int) -> Unit = { _ -> }, + onResetMtu: () -> Unit = {}, + onDismiss: () -> Unit = {}, + ) { + MtuDialog( + mtuInitial = mtuInitial, + onSaveMtu = onSaveMtu, + onResetMtu = onResetMtu, + onDismiss = onDismiss + ) + } + + @Test + fun testMtuDialogWithDefaultValue() { + // Arrange + composeTestRule.setContentWithTheme { testMtuDialog() } + + // Assert + composeTestRule.onNodeWithText(EMPTY_STRING).assertExists() + } + + @Test + fun testMtuDialogWithEditValue() { + // Arrange + composeTestRule.setContentWithTheme { + testMtuDialog( + mtuInitial = VALID_DUMMY_MTU_VALUE, + ) + } + + // Assert + composeTestRule.onNodeWithText(VALID_DUMMY_MTU_VALUE.toString()).assertExists() + } + + @Test + fun testMtuDialogTextInput() { + // Arrange + composeTestRule.setContentWithTheme { + testMtuDialog( + null, + ) + } + + // Act + composeTestRule + .onNodeWithText(EMPTY_STRING) + .performTextInput(VALID_DUMMY_MTU_VALUE.toString()) + + // Assert + composeTestRule.onNodeWithText(VALID_DUMMY_MTU_VALUE.toString()).assertExists() + } + + @Test + fun testMtuDialogSubmitOfValidValue() { + // Arrange + val mockedSubmitHandler: (Int) -> Unit = mockk(relaxed = true) + composeTestRule.setContentWithTheme { + testMtuDialog( + VALID_DUMMY_MTU_VALUE, + onSaveMtu = mockedSubmitHandler, + ) + } + + // Act + composeTestRule.onNodeWithText("Submit").assertIsEnabled().performClick() + + // Assert + verify { mockedSubmitHandler.invoke(VALID_DUMMY_MTU_VALUE) } + } + + @Test + fun testMtuDialogSubmitButtonDisabledWhenInvalidInput() { + // Arrange + composeTestRule.setContentWithTheme { + testMtuDialog( + INVALID_DUMMY_MTU_VALUE, + ) + } + + // Assert + composeTestRule.onNodeWithText("Submit").assertIsNotEnabled() + } + + @Test + fun testMtuDialogResetClick() { + // Arrange + val mockedClickHandler: () -> Unit = mockk(relaxed = true) + composeTestRule.setContentWithTheme { + testMtuDialog( + onResetMtu = mockedClickHandler, + ) + } + + // Act + composeTestRule.onNodeWithText("Reset to default").performClick() + + // Assert + verify { mockedClickHandler.invoke() } + } + + @Test + fun testMtuDialogCancelClick() { + // Arrange + val mockedClickHandler: () -> Unit = mockk(relaxed = true) + composeTestRule.setContentWithTheme { + testMtuDialog( + onDismiss = mockedClickHandler, + ) + } + + // Assert + composeTestRule.onNodeWithText("Cancel").performClick() + + // Assert + verify { mockedClickHandler.invoke() } + } + + companion object { + private const val EMPTY_STRING = "" + private const val VALID_DUMMY_MTU_VALUE = 1337 + private const val INVALID_DUMMY_MTU_VALUE = 1111 + } +} diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/PaymentDialogTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/PaymentDialogTest.kt new file mode 100644 index 0000000000..1a626ecf19 --- /dev/null +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/PaymentDialogTest.kt @@ -0,0 +1,57 @@ +package net.mullvad.mullvadvpn.compose.dialog + +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import net.mullvad.mullvadvpn.compose.dialog.payment.PaymentDialog +import net.mullvad.mullvadvpn.compose.setContentWithTheme +import net.mullvad.mullvadvpn.lib.payment.model.ProductId +import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult +import net.mullvad.mullvadvpn.util.toPaymentDialogData +import org.junit.Rule +import org.junit.Test + +class PaymentDialogTest { + @get:Rule val composeTestRule = createComposeRule() + + @Test + fun testShowPurchaseCompleteDialog() { + // Arrange + composeTestRule.setContentWithTheme { + PaymentDialog( + paymentDialogData = PurchaseResult.Completed.Success.toPaymentDialogData()!! + ) + } + + // Assert + composeTestRule.onNodeWithText("Time was successfully added").assertExists() + } + + @Test + fun testShowVerificationErrorDialog() { + // Arrange + composeTestRule.setContentWithTheme { + PaymentDialog( + paymentDialogData = + PurchaseResult.Error.VerificationError(null).toPaymentDialogData()!! + ) + } + + // Assert + composeTestRule.onNodeWithText("Verifying purchase").assertExists() + } + + @Test + fun testShowFetchProductsErrorDialog() { + // Arrange + composeTestRule.setContentWithTheme { + PaymentDialog( + paymentDialogData = + PurchaseResult.Error.FetchProductsError(ProductId(""), null) + .toPaymentDialogData()!! + ) + } + + // Assert + composeTestRule.onNodeWithText("Google Play unavailable").assertExists() + } +} diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt index e997ae29e4..3b42cc1c3b 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt @@ -1,6 +1,5 @@ package net.mullvad.mullvadvpn.compose.screen -import android.app.Activity import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag @@ -19,8 +18,6 @@ import net.mullvad.mullvadvpn.lib.payment.model.PaymentProduct import net.mullvad.mullvadvpn.lib.payment.model.PaymentStatus import net.mullvad.mullvadvpn.lib.payment.model.ProductId import net.mullvad.mullvadvpn.lib.payment.model.ProductPrice -import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult -import net.mullvad.mullvadvpn.util.toPaymentDialogData import net.mullvad.mullvadvpn.viewmodel.AccountUiState import net.mullvad.mullvadvpn.viewmodel.AccountViewModel import org.junit.Before @@ -41,15 +38,14 @@ class AccountScreenTest { // Arrange composeTestRule.setContentWithTheme { AccountScreen( - showSitePayment = true, uiState = AccountUiState( deviceName = DUMMY_DEVICE_NAME, accountNumber = DUMMY_ACCOUNT_NUMBER, - accountExpiry = null + accountExpiry = null, + showSitePayment = false ), uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() ) } @@ -66,15 +62,14 @@ class AccountScreenTest { val mockedClickHandler: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { AccountScreen( - showSitePayment = true, uiState = AccountUiState( + showSitePayment = true, deviceName = DUMMY_DEVICE_NAME, accountNumber = DUMMY_ACCOUNT_NUMBER, - accountExpiry = null + accountExpiry = null, ), uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow(), onManageAccountClick = mockedClickHandler ) } @@ -92,15 +87,14 @@ class AccountScreenTest { val mockedClickHandler: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { AccountScreen( - showSitePayment = true, uiState = AccountUiState( deviceName = DUMMY_DEVICE_NAME, accountNumber = DUMMY_ACCOUNT_NUMBER, - accountExpiry = null + accountExpiry = null, + showSitePayment = false ), uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow(), onRedeemVoucherClick = mockedClickHandler ) } @@ -118,15 +112,14 @@ class AccountScreenTest { val mockedClickHandler: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { AccountScreen( - showSitePayment = true, uiState = AccountUiState( deviceName = DUMMY_DEVICE_NAME, accountNumber = DUMMY_ACCOUNT_NUMBER, - accountExpiry = null + accountExpiry = null, + showSitePayment = false ), uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow(), onLogoutClick = mockedClickHandler ) } @@ -139,79 +132,13 @@ class AccountScreenTest { } @Test - fun testShowPurchaseCompleteDialog() { - // Arrange - composeTestRule.setContentWithTheme { - AccountScreen( - showSitePayment = true, - uiState = - AccountUiState.default() - .copy( - paymentDialogData = - PurchaseResult.Completed.Success.toPaymentDialogData() - ), - uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText("Time was successfully added").assertExists() - } - - @Test - fun testShowVerificationErrorDialog() { - // Arrange - composeTestRule.setContentWithTheme { - AccountScreen( - showSitePayment = true, - uiState = - AccountUiState.default() - .copy( - paymentDialogData = - PurchaseResult.Error.VerificationError(null).toPaymentDialogData() - ), - uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText("Verifying purchase").assertExists() - } - - @Test - fun testShowFetchProductsErrorDialog() { - // Arrange - composeTestRule.setContentWithTheme { - AccountScreen( - showSitePayment = true, - uiState = - AccountUiState.default() - .copy( - paymentDialogData = - PurchaseResult.Error.FetchProductsError(ProductId(""), null) - .toPaymentDialogData() - ), - uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText("Google Play unavailable").assertExists() - } - - @Test fun testShowBillingErrorPaymentButton() { // Arrange composeTestRule.setContentWithTheme { AccountScreen( - showSitePayment = true, uiState = AccountUiState.default().copy(billingPaymentState = PaymentState.Error.Billing), uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() ) } @@ -227,7 +154,6 @@ class AccountScreenTest { every { mockPaymentProduct.status } returns null composeTestRule.setContentWithTheme { AccountScreen( - showSitePayment = true, uiState = AccountUiState.default() .copy( @@ -235,7 +161,6 @@ class AccountScreenTest { PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) ), uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() ) } @@ -251,7 +176,6 @@ class AccountScreenTest { every { mockPaymentProduct.status } returns PaymentStatus.PENDING composeTestRule.setContentWithTheme { AccountScreen( - showSitePayment = true, uiState = AccountUiState.default() .copy( @@ -259,7 +183,6 @@ class AccountScreenTest { PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) ), uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() ) } @@ -273,9 +196,9 @@ class AccountScreenTest { val mockPaymentProduct: PaymentProduct = mockk() every { mockPaymentProduct.price } returns ProductPrice("$10") every { mockPaymentProduct.status } returns PaymentStatus.PENDING + val mockNavigateToVerificationPending: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { AccountScreen( - showSitePayment = true, uiState = AccountUiState.default() .copy( @@ -283,7 +206,7 @@ class AccountScreenTest { PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) ), uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() + navigateToVerificationPendingDialog = mockNavigateToVerificationPending ) } @@ -291,11 +214,7 @@ class AccountScreenTest { composeTestRule.onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).performClick() // Assert - composeTestRule - .onNodeWithText( - "We are currently verifying your purchase, this might take some time. Your time will be added if the verification is successful." - ) - .assertExists() + verify(exactly = 1) { mockNavigateToVerificationPending.invoke() } } @Test @@ -306,7 +225,6 @@ class AccountScreenTest { every { mockPaymentProduct.status } returns PaymentStatus.VERIFICATION_IN_PROGRESS composeTestRule.setContentWithTheme { AccountScreen( - showSitePayment = true, uiState = AccountUiState.default() .copy( @@ -314,7 +232,6 @@ class AccountScreenTest { PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) ), uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() ) } @@ -325,14 +242,13 @@ class AccountScreenTest { @Test fun testOnPurchaseBillingProductClick() { // Arrange - val clickHandler: (ProductId, () -> Activity) -> Unit = mockk(relaxed = true) + val clickHandler: (ProductId) -> Unit = mockk(relaxed = true) val mockPaymentProduct: PaymentProduct = mockk() every { mockPaymentProduct.price } returns ProductPrice("$10") every { mockPaymentProduct.productId } returns ProductId("PRODUCT_ID") every { mockPaymentProduct.status } returns null composeTestRule.setContentWithTheme { AccountScreen( - showSitePayment = true, uiState = AccountUiState.default() .copy( @@ -341,7 +257,6 @@ class AccountScreenTest { ), onPurchaseBillingProductClick = clickHandler, uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() ) } @@ -349,7 +264,7 @@ class AccountScreenTest { composeTestRule.onNodeWithText("Add 30 days time ($10)").performClick() // Assert - verify { clickHandler.invoke(ProductId("PRODUCT_ID"), any()) } + verify { clickHandler.invoke(ProductId("PRODUCT_ID")) } } companion object { diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogDialogTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogDialogTest.kt index ab8f2b1512..4e34fe0825 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogDialogTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogDialogTest.kt @@ -9,10 +9,9 @@ import io.mockk.every import io.mockk.impl.annotations.MockK import io.mockk.just import io.mockk.verify -import kotlinx.coroutines.flow.MutableStateFlow import net.mullvad.mullvadvpn.compose.dialog.ChangelogDialog import net.mullvad.mullvadvpn.compose.setContentWithTheme -import net.mullvad.mullvadvpn.viewmodel.ChangelogDialogUiState +import net.mullvad.mullvadvpn.viewmodel.Changelog import net.mullvad.mullvadvpn.viewmodel.ChangelogViewModel import org.junit.Before import org.junit.Rule @@ -29,17 +28,17 @@ class ChangelogDialogTest { } @Test - fun testShowChangeLogWhenNeeded() { + fun testShowChangelogWhenNeeded() { // Arrange - every { mockedViewModel.uiState } returns - MutableStateFlow(ChangelogDialogUiState.Show(listOf(CHANGELOG_ITEM))) - every { mockedViewModel.dismissChangelogDialog() } just Runs + every { mockedViewModel.markChangelogAsRead() } just Runs composeTestRule.setContentWithTheme { ChangelogDialog( - changesList = listOf(CHANGELOG_ITEM), - version = CHANGELOG_VERSION, - onDismiss = { mockedViewModel.dismissChangelogDialog() } + Changelog( + changes = listOf(CHANGELOG_ITEM), + version = CHANGELOG_VERSION, + ), + onDismiss = { mockedViewModel.markChangelogAsRead() } ) } @@ -50,7 +49,7 @@ class ChangelogDialogTest { composeTestRule.onNodeWithText(CHANGELOG_BUTTON_TEXT).performClick() // Assert - verify { mockedViewModel.dismissChangelogDialog() } + verify { mockedViewModel.markChangelogAsRead() } } companion object { 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 56894addea..cd25c8ce0b 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 @@ -9,9 +9,6 @@ import io.mockk.every import io.mockk.mockk import io.mockk.unmockkAll import io.mockk.verify -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asSharedFlow import net.mullvad.mullvadvpn.compose.setContentWithTheme import net.mullvad.mullvadvpn.compose.state.ConnectUiState import net.mullvad.mullvadvpn.compose.test.CIRCULAR_PROGRESS_INDICATOR @@ -21,12 +18,12 @@ import net.mullvad.mullvadvpn.compose.test.NOTIFICATION_BANNER_ACTION import net.mullvad.mullvadvpn.compose.test.RECONNECT_BUTTON_TEST_TAG import net.mullvad.mullvadvpn.compose.test.SCROLLABLE_COLUMN_TEST_TAG import net.mullvad.mullvadvpn.compose.test.SELECT_LOCATION_BUTTON_TEST_TAG +import net.mullvad.mullvadvpn.compose.test.TOP_BAR_ACCOUNT_BUTTON import net.mullvad.mullvadvpn.model.GeoIpLocation import net.mullvad.mullvadvpn.model.TunnelState import net.mullvad.mullvadvpn.relaylist.RelayItem import net.mullvad.mullvadvpn.repository.InAppNotification import net.mullvad.mullvadvpn.ui.VersionInfo -import net.mullvad.mullvadvpn.viewmodel.ConnectViewModel import net.mullvad.talpid.net.TransportProtocol import net.mullvad.talpid.net.TunnelEndpoint import net.mullvad.talpid.tunnel.ActionAfterDisconnect @@ -57,7 +54,6 @@ class ConnectScreenTest { composeTestRule.setContentWithTheme { ConnectScreen( uiState = ConnectUiState.INITIAL, - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -88,7 +84,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = InAppNotification.TunnelStateBlocked ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -124,7 +119,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = InAppNotification.TunnelStateBlocked ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -158,7 +152,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = null ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -191,7 +184,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = null ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -225,7 +217,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = null ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -259,7 +250,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = null ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -298,7 +288,6 @@ class ConnectScreenTest { ErrorState(ErrorStateCause.StartTunnelError, true) ) ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -338,7 +327,6 @@ class ConnectScreenTest { ErrorState(ErrorStateCause.StartTunnelError, false) ) ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -372,7 +360,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = InAppNotification.TunnelStateBlocked ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -408,7 +395,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = InAppNotification.TunnelStateBlocked ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -444,7 +430,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = null ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow(), onSwitchLocationClick = mockedClickHandler ) } @@ -477,7 +462,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = null ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow(), onDisconnectClick = mockedClickHandler ) } @@ -510,7 +494,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = null ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow(), onReconnectClick = mockedClickHandler ) } @@ -542,7 +525,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = null ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow(), onConnectClick = mockedClickHandler ) } @@ -574,7 +556,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = null ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow(), onCancelClick = mockedClickHandler ) } @@ -607,7 +588,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = null ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow(), onToggleTunnelInfo = mockedClickHandler ) } @@ -647,7 +627,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = null ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -686,7 +665,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = InAppNotification.UpdateAvailable(versionInfo) ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -723,7 +701,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = InAppNotification.UnsupportedVersion(versionInfo) ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -757,7 +734,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = InAppNotification.AccountExpiry(expiryDate) ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -796,7 +772,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = InAppNotification.UnsupportedVersion(versionInfo) ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -829,7 +804,6 @@ class ConnectScreenTest { daysLeftUntilExpiry = null, inAppNotification = InAppNotification.AccountExpiry(expiryDate) ), - uiSideEffect = MutableSharedFlow<ConnectViewModel.UiSideEffect>().asSharedFlow() ) } @@ -842,34 +816,17 @@ class ConnectScreenTest { @Test fun testOpenAccountView() { - // Arrange - composeTestRule.setContentWithTheme { - ConnectScreen( - uiState = ConnectUiState.INITIAL, - uiSideEffect = - MutableStateFlow( - ConnectViewModel.UiSideEffect.OpenAccountManagementPageInBrowser("222") - ) - ) - } - // Assert - composeTestRule.apply { onNodeWithTag(SCROLLABLE_COLUMN_TEST_TAG).assertDoesNotExist() } - } + val onAccountClickMockk: () -> Unit = mockk(relaxed = true) - @Test - fun testOpenOutOfTimeScreen() { // Arrange - val mockedOpenScreenHandler: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { - ConnectScreen( - uiState = ConnectUiState.INITIAL, - uiSideEffect = MutableStateFlow(ConnectViewModel.UiSideEffect.OpenOutOfTimeView), - onOpenOutOfTimeScreen = mockedOpenScreenHandler - ) + ConnectScreen(uiState = ConnectUiState.INITIAL, onAccountClick = onAccountClickMockk) } // Assert - verify { mockedOpenScreenHandler.invoke() } + composeTestRule.onNodeWithTag(TOP_BAR_ACCOUNT_BUTTON).performClick() + + verify(exactly = 1) { onAccountClickMockk() } } } diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreenTest.kt index b5f762b89b..32fd727329 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreenTest.kt @@ -6,7 +6,6 @@ import androidx.compose.ui.test.performClick import io.mockk.MockKAnnotations import io.mockk.mockk import io.mockk.verify -import kotlinx.coroutines.flow.MutableSharedFlow import net.mullvad.mullvadvpn.compose.setContentWithTheme import net.mullvad.mullvadvpn.compose.state.RelayFilterState import net.mullvad.mullvadvpn.model.Ownership @@ -31,8 +30,7 @@ class FilterScreenTest { selectedOwnership = null, selectedProviders = DUMMY_SELECTED_PROVIDERS, ), - uiCloseAction = MutableSharedFlow(), - onSelectedProviders = { _, _ -> } + onSelectedProvider = { _, _ -> } ) } composeTestRule.apply { @@ -51,8 +49,7 @@ class FilterScreenTest { selectedOwnership = null, selectedProviders = DUMMY_SELECTED_PROVIDERS ), - uiCloseAction = MutableSharedFlow(), - onSelectedProviders = { _, _ -> } + onSelectedProvider = { _, _ -> } ) } composeTestRule.apply { @@ -71,8 +68,7 @@ class FilterScreenTest { selectedOwnership = Ownership.MullvadOwned, selectedProviders = DUMMY_SELECTED_PROVIDERS ), - uiCloseAction = MutableSharedFlow(), - onSelectedProviders = { _, _ -> } + onSelectedProvider = { _, _ -> } ) } composeTestRule.apply { @@ -91,8 +87,7 @@ class FilterScreenTest { selectedOwnership = Ownership.Rented, selectedProviders = DUMMY_SELECTED_PROVIDERS ), - uiCloseAction = MutableSharedFlow(), - onSelectedProviders = { _, _ -> } + onSelectedProvider = { _, _ -> } ) } composeTestRule.apply { @@ -111,8 +106,7 @@ class FilterScreenTest { selectedOwnership = null, selectedProviders = DUMMY_SELECTED_PROVIDERS ), - uiCloseAction = MutableSharedFlow(), - onSelectedProviders = { _, _ -> } + onSelectedProvider = { _, _ -> } ) } @@ -135,8 +129,7 @@ class FilterScreenTest { selectedOwnership = null, selectedProviders = listOf(Provider("31173", true)) ), - uiCloseAction = MutableSharedFlow(), - onSelectedProviders = { _, _ -> }, + onSelectedProvider = { _, _ -> }, onApplyClick = mockClickListener ) } diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt index 28e2519c81..d43a0931a1 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt @@ -1,6 +1,5 @@ package net.mullvad.mullvadvpn.compose.screen -import android.app.Activity import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText @@ -9,9 +8,6 @@ import io.mockk.MockKAnnotations import io.mockk.every import io.mockk.mockk import io.mockk.verify -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asSharedFlow import net.mullvad.mullvadvpn.compose.setContentWithTheme import net.mullvad.mullvadvpn.compose.state.OutOfTimeUiState import net.mullvad.mullvadvpn.compose.state.PaymentState @@ -20,10 +16,7 @@ import net.mullvad.mullvadvpn.lib.payment.model.PaymentProduct import net.mullvad.mullvadvpn.lib.payment.model.PaymentStatus import net.mullvad.mullvadvpn.lib.payment.model.ProductId import net.mullvad.mullvadvpn.lib.payment.model.ProductPrice -import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult import net.mullvad.mullvadvpn.model.TunnelState -import net.mullvad.mullvadvpn.util.toPaymentDialogData -import net.mullvad.mullvadvpn.viewmodel.OutOfTimeViewModel import org.junit.Before import org.junit.Rule import org.junit.Test @@ -41,14 +34,11 @@ class OutOfTimeScreenTest { // Arrange composeTestRule.setContentWithTheme { OutOfTimeScreen( - showSitePayment = false, uiState = OutOfTimeUiState(deviceName = ""), - uiSideEffect = MutableSharedFlow(), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, onDisconnectClick = {} ) } @@ -69,15 +59,11 @@ class OutOfTimeScreenTest { // Arrange composeTestRule.setContentWithTheme { OutOfTimeScreen( - showSitePayment = true, - uiState = OutOfTimeUiState(deviceName = ""), - uiSideEffect = - MutableStateFlow(OutOfTimeViewModel.UiSideEffect.OpenAccountView("222")), + uiState = OutOfTimeUiState(deviceName = "", showSitePayment = true), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, onDisconnectClick = {} ) } @@ -87,41 +73,16 @@ class OutOfTimeScreenTest { } @Test - fun testOpenConnectScreen() { - // Arrange - val mockClickListener: () -> Unit = mockk(relaxed = true) - composeTestRule.setContentWithTheme { - OutOfTimeScreen( - showSitePayment = true, - uiState = OutOfTimeUiState(deviceName = ""), - uiSideEffect = MutableStateFlow(OutOfTimeViewModel.UiSideEffect.OpenConnectScreen), - onSitePaymentClick = {}, - onRedeemVoucherClick = {}, - onSettingsClick = {}, - onAccountClick = {}, - openConnectScreen = mockClickListener, - onDisconnectClick = {} - ) - } - - // Assert - verify(exactly = 1) { mockClickListener.invoke() } - } - - @Test fun testClickSitePaymentButton() { // Arrange val mockClickListener: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { OutOfTimeScreen( - showSitePayment = true, - uiState = OutOfTimeUiState(deviceName = ""), - uiSideEffect = MutableSharedFlow(), + uiState = OutOfTimeUiState(deviceName = "", showSitePayment = true), onSitePaymentClick = mockClickListener, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, onDisconnectClick = {} ) } @@ -139,14 +100,11 @@ class OutOfTimeScreenTest { val mockClickListener: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { OutOfTimeScreen( - showSitePayment = true, - uiState = OutOfTimeUiState(deviceName = ""), - uiSideEffect = MutableSharedFlow(), + uiState = OutOfTimeUiState(deviceName = "", showSitePayment = true), onSitePaymentClick = {}, onRedeemVoucherClick = mockClickListener, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, onDisconnectClick = {} ) } @@ -164,18 +122,16 @@ class OutOfTimeScreenTest { val mockClickListener: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { OutOfTimeScreen( - showSitePayment = true, uiState = OutOfTimeUiState( tunnelState = TunnelState.Connecting(null, null), - deviceName = "" + deviceName = "", + showSitePayment = true ), - uiSideEffect = MutableSharedFlow(), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, onDisconnectClick = mockClickListener ) } @@ -188,89 +144,20 @@ class OutOfTimeScreenTest { } @Test - fun testShowPurchaseCompleteDialog() { - // Arrange - composeTestRule.setContentWithTheme { - OutOfTimeScreen( - showSitePayment = true, - uiState = - OutOfTimeUiState( - paymentDialogData = PurchaseResult.Completed.Success.toPaymentDialogData() - ), - uiSideEffect = MutableStateFlow(OutOfTimeViewModel.UiSideEffect.OpenConnectScreen), - onSitePaymentClick = {}, - onRedeemVoucherClick = {}, - onSettingsClick = {}, - onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> } - ) - } - - // Assert - composeTestRule.onNodeWithText("Time was successfully added").assertExists() - } - - @Test - fun testShowVerificationErrorDialog() { + fun testShowBillingErrorPaymentButton() { // Arrange composeTestRule.setContentWithTheme { OutOfTimeScreen( - showSitePayment = true, uiState = OutOfTimeUiState( - paymentDialogData = - PurchaseResult.Error.VerificationError(null).toPaymentDialogData() + showSitePayment = true, + billingPaymentState = PaymentState.Error.Billing ), - uiSideEffect = MutableStateFlow(OutOfTimeViewModel.UiSideEffect.OpenConnectScreen), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> } - ) - } - - // Assert - composeTestRule.onNodeWithText("Verifying purchase").assertExists() - } - - @Test - fun testShowFetchProductsErrorDialog() { - // Arrange - composeTestRule.setContentWithTheme { - OutOfTimeScreen( - showSitePayment = true, - uiState = - OutOfTimeUiState() - .copy( - paymentDialogData = - PurchaseResult.Error.FetchProductsError(ProductId(""), null) - .toPaymentDialogData() - ), - uiSideEffect = MutableSharedFlow<OutOfTimeViewModel.UiSideEffect>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText("Google Play unavailable").assertExists() - } - - @Test - fun testShowBillingErrorPaymentButton() { - // Arrange - composeTestRule.setContentWithTheme { - OutOfTimeScreen( - showSitePayment = true, - uiState = OutOfTimeUiState().copy(billingPaymentState = PaymentState.Error.Billing), - uiSideEffect = MutableSharedFlow<OutOfTimeViewModel.UiSideEffect>().asSharedFlow(), - onSitePaymentClick = {}, - onRedeemVoucherClick = {}, - onSettingsClick = {}, - onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> } + onPurchaseBillingProductClick = { _ -> } ) } @@ -286,19 +173,17 @@ class OutOfTimeScreenTest { every { mockPaymentProduct.status } returns null composeTestRule.setContentWithTheme { OutOfTimeScreen( - showSitePayment = true, uiState = OutOfTimeUiState( + showSitePayment = true, billingPaymentState = PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) ), - uiSideEffect = MutableStateFlow(OutOfTimeViewModel.UiSideEffect.OpenConnectScreen), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> } + onPurchaseBillingProductClick = { _ -> } ) } @@ -314,14 +199,12 @@ class OutOfTimeScreenTest { every { mockPaymentProduct.status } returns PaymentStatus.PENDING composeTestRule.setContentWithTheme { OutOfTimeScreen( - showSitePayment = true, uiState = - OutOfTimeUiState() - .copy( - billingPaymentState = - PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) - ), - uiSideEffect = MutableSharedFlow<OutOfTimeViewModel.UiSideEffect>().asSharedFlow() + OutOfTimeUiState( + showSitePayment = true, + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), ) } @@ -335,28 +218,24 @@ class OutOfTimeScreenTest { val mockPaymentProduct: PaymentProduct = mockk() every { mockPaymentProduct.price } returns ProductPrice("$10") every { mockPaymentProduct.status } returns PaymentStatus.PENDING + val mockNavigateToVerificationPending: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { OutOfTimeScreen( - showSitePayment = true, uiState = - OutOfTimeUiState() - .copy( - billingPaymentState = - PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) - ), - uiSideEffect = MutableSharedFlow<OutOfTimeViewModel.UiSideEffect>().asSharedFlow() + OutOfTimeUiState( + showSitePayment = true, + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + navigateToVerificationPendingDialog = mockNavigateToVerificationPending ) } // Act composeTestRule.onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).performClick() + composeTestRule.onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).assertExists() - // Assert - composeTestRule - .onNodeWithText( - "We are currently verifying your purchase, this might take some time. Your time will be added if the verification is successful." - ) - .assertExists() + verify(exactly = 1) { mockNavigateToVerificationPending.invoke() } } @Test @@ -367,14 +246,12 @@ class OutOfTimeScreenTest { every { mockPaymentProduct.status } returns PaymentStatus.VERIFICATION_IN_PROGRESS composeTestRule.setContentWithTheme { OutOfTimeScreen( - showSitePayment = true, uiState = - OutOfTimeUiState() - .copy( - billingPaymentState = - PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) - ), - uiSideEffect = MutableSharedFlow<OutOfTimeViewModel.UiSideEffect>().asSharedFlow() + OutOfTimeUiState( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)), + showSitePayment = true, + ) ) } @@ -385,25 +262,23 @@ class OutOfTimeScreenTest { @Test fun testOnPurchaseBillingProductClick() { // Arrange - val clickHandler: (ProductId, () -> Activity) -> Unit = mockk(relaxed = true) + val clickHandler: (ProductId) -> Unit = mockk(relaxed = true) val mockPaymentProduct: PaymentProduct = mockk() every { mockPaymentProduct.price } returns ProductPrice("$10") every { mockPaymentProduct.productId } returns ProductId("PRODUCT_ID") every { mockPaymentProduct.status } returns null composeTestRule.setContentWithTheme { OutOfTimeScreen( - showSitePayment = true, uiState = OutOfTimeUiState( billingPaymentState = - PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)), + showSitePayment = true, ), - uiSideEffect = MutableStateFlow(OutOfTimeViewModel.UiSideEffect.OpenConnectScreen), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, onPurchaseBillingProductClick = clickHandler ) } @@ -412,6 +287,6 @@ class OutOfTimeScreenTest { composeTestRule.onNodeWithText("Add 30 days time ($10)").performClick() // Assert - verify { clickHandler(ProductId("PRODUCT_ID"), any()) } + verify { clickHandler(ProductId("PRODUCT_ID")) } } } diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/RedeemVoucherDialogTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/RedeemVoucherDialogTest.kt index c07cb1aa6b..5a51a8f885 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/RedeemVoucherDialogTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/RedeemVoucherDialogTest.kt @@ -8,6 +8,7 @@ import androidx.compose.ui.test.performTextInput import io.mockk.mockk import io.mockk.mockkObject import io.mockk.verify +import net.mullvad.mullvadvpn.compose.dialog.RedeemVoucherDialog import net.mullvad.mullvadvpn.compose.setContentWithTheme import net.mullvad.mullvadvpn.compose.state.VoucherDialogState import net.mullvad.mullvadvpn.compose.state.VoucherDialogUiState @@ -30,7 +31,7 @@ class RedeemVoucherDialogTest { // Arrange val mockedClickHandler: (Boolean) -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { - RedeemVoucherDialogScreen( + RedeemVoucherDialog( uiState = VoucherDialogUiState.INITIAL, onVoucherInputChange = {}, onRedeem = {}, @@ -50,7 +51,7 @@ class RedeemVoucherDialogTest { // Arrange val mockedClickHandler: (Boolean) -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { - RedeemVoucherDialogScreen( + RedeemVoucherDialog( uiState = VoucherDialogUiState(voucherViewModelState = VoucherDialogState.Success(0)), onVoucherInputChange = {}, @@ -71,7 +72,7 @@ class RedeemVoucherDialogTest { // Arrange val mockedClickHandler: (String) -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { - RedeemVoucherDialogScreen( + RedeemVoucherDialog( uiState = VoucherDialogUiState(), onVoucherInputChange = mockedClickHandler, onRedeem = {}, @@ -90,7 +91,7 @@ class RedeemVoucherDialogTest { fun testVerifyingState() { // Arrange composeTestRule.setContentWithTheme { - RedeemVoucherDialogScreen( + RedeemVoucherDialog( uiState = VoucherDialogUiState(voucherViewModelState = VoucherDialogState.Verifying), onVoucherInputChange = {}, @@ -107,7 +108,7 @@ class RedeemVoucherDialogTest { fun testSuccessState() { // Arrange composeTestRule.setContentWithTheme { - RedeemVoucherDialogScreen( + RedeemVoucherDialog( uiState = VoucherDialogUiState(voucherViewModelState = VoucherDialogState.Success(0)), onVoucherInputChange = {}, @@ -124,7 +125,7 @@ class RedeemVoucherDialogTest { fun testErrorState() { // Arrange composeTestRule.setContentWithTheme { - RedeemVoucherDialogScreen( + RedeemVoucherDialog( uiState = VoucherDialogUiState( voucherViewModelState = VoucherDialogState.Error(ERROR_MESSAGE) diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreenTest.kt index 7e66bc24d9..ea1d261689 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreenTest.kt @@ -7,8 +7,6 @@ import androidx.compose.ui.test.performTextInput import io.mockk.MockKAnnotations import io.mockk.mockk import io.mockk.verify -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.asSharedFlow import net.mullvad.mullvadvpn.compose.setContentWithTheme import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState import net.mullvad.mullvadvpn.compose.test.CIRCULAR_PROGRESS_INDICATOR @@ -39,8 +37,6 @@ class SelectLocationScreenTest { composeTestRule.setContentWithTheme { SelectLocationScreen( uiState = SelectLocationUiState.Loading, - uiCloseAction = MutableSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() ) } @@ -61,8 +57,6 @@ class SelectLocationScreenTest { selectedProvidersCount = 0, searchTerm = "" ), - uiCloseAction = MutableSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() ) } @@ -101,8 +95,6 @@ class SelectLocationScreenTest { selectedProvidersCount = 0, searchTerm = "" ), - uiCloseAction = MutableSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() ) } @@ -131,8 +123,6 @@ class SelectLocationScreenTest { selectedProvidersCount = 0, searchTerm = "" ), - uiCloseAction = MutableSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow(), onSearchTermInput = mockedSearchTermInput ) } @@ -160,8 +150,6 @@ class SelectLocationScreenTest { selectedProvidersCount = 0, searchTerm = mockSearchString ), - uiCloseAction = MutableSharedFlow(), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow(), onSearchTermInput = mockedSearchTermInput ) } diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreenTest.kt index 576660551e..e15ed012d6 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreenTest.kt @@ -4,8 +4,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithText import io.mockk.MockKAnnotations -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.asSharedFlow import net.mullvad.mullvadvpn.compose.setContentWithTheme import net.mullvad.mullvadvpn.compose.state.SettingsUiState import org.junit.Before @@ -28,7 +26,6 @@ class SettingsScreenTest { SettingsScreen( uiState = SettingsUiState(appVersion = "", isLoggedIn = true, isUpdateAvailable = true), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() ) } // Assert @@ -47,7 +44,6 @@ class SettingsScreenTest { SettingsScreen( uiState = SettingsUiState(appVersion = "", isLoggedIn = false, isUpdateAvailable = true), - enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() ) } // Assert 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 9b6dd9e492..1ca2b3e1f7 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 @@ -1,7 +1,5 @@ package net.mullvad.mullvadvpn.compose.screen -import androidx.compose.ui.test.assertIsEnabled -import androidx.compose.ui.test.assertIsNotEnabled import androidx.compose.ui.test.hasTestTag import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithContentDescription @@ -9,16 +7,11 @@ import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollToNode -import androidx.compose.ui.test.performTextInput import io.mockk.MockKAnnotations import io.mockk.mockk import io.mockk.verify -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.asSharedFlow import net.mullvad.mullvadvpn.compose.setContentWithTheme -import net.mullvad.mullvadvpn.compose.state.VpnSettingsDialog import net.mullvad.mullvadvpn.compose.state.VpnSettingsUiState -import net.mullvad.mullvadvpn.compose.test.CUSTOM_PORT_DIALOG_INPUT_TEST_TAG 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 @@ -32,7 +25,6 @@ import net.mullvad.mullvadvpn.model.PortRange import net.mullvad.mullvadvpn.model.QuantumResistantState import net.mullvad.mullvadvpn.onNodeWithTagAndText import net.mullvad.mullvadvpn.viewmodel.CustomDnsItem -import net.mullvad.mullvadvpn.viewmodel.StagedDns import org.junit.Before import org.junit.Rule import org.junit.Test @@ -51,7 +43,6 @@ class VpnSettingsScreenTest { composeTestRule.setContentWithTheme { VpnSettingsScreen( uiState = VpnSettingsUiState.createDefault(), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() ) } @@ -74,7 +65,6 @@ class VpnSettingsScreenTest { composeTestRule.setContentWithTheme { VpnSettingsScreen( uiState = VpnSettingsUiState.createDefault(mtu = VALID_DUMMY_MTU_VALUE), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() ) } @@ -87,166 +77,6 @@ class VpnSettingsScreenTest { } @Test - fun testMtuClick() { - // Arrange - val mockedClickHandler: () -> Unit = mockk(relaxed = true) - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = VpnSettingsUiState.createDefault(), - onMtuCellClick = mockedClickHandler, - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - composeTestRule - .onNodeWithTag(LAZY_LIST_TEST_TAG) - .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG)) - - // Act - composeTestRule.onNodeWithText("WireGuard MTU").performClick() - - // Assert - verify { mockedClickHandler.invoke() } - } - - @Test - fun testMtuDialogWithDefaultValue() { - // Arrange - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = VpnSettingsDialog.Mtu(mtuEditValue = EMPTY_STRING), - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText(EMPTY_STRING).assertExists() - } - - @Test - fun testMtuDialogWithEditValue() { - // Arrange - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = VpnSettingsDialog.Mtu(mtuEditValue = VALID_DUMMY_MTU_VALUE) - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText(VALID_DUMMY_MTU_VALUE).assertExists() - } - - @Test - fun testMtuDialogTextInput() { - // Arrange - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = VpnSettingsDialog.Mtu(mtuEditValue = EMPTY_STRING) - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Act - composeTestRule.onNodeWithText(EMPTY_STRING).performTextInput(VALID_DUMMY_MTU_VALUE) - - // Assert - composeTestRule.onNodeWithText(VALID_DUMMY_MTU_VALUE).assertExists() - } - - @Test - fun testMtuDialogSubmitOfValidValue() { - // Arrange - val mockedSubmitHandler: (Int) -> Unit = mockk(relaxed = true) - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = VpnSettingsDialog.Mtu(mtuEditValue = VALID_DUMMY_MTU_VALUE) - ), - onSaveMtuClick = mockedSubmitHandler, - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Act - composeTestRule.onNodeWithText("Submit").assertIsEnabled().performClick() - - // Assert - verify { mockedSubmitHandler.invoke(VALID_DUMMY_MTU_VALUE.toInt()) } - } - - @Test - fun testMtuDialogSubmitButtonDisabledWhenInvalidInput() { - // Arrange - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = VpnSettingsDialog.Mtu(mtuEditValue = INVALID_DUMMY_MTU_VALUE) - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText("Submit").assertIsNotEnabled() - } - - @Test - fun testMtuDialogResetClick() { - // Arrange - val mockedClickHandler: () -> Unit = mockk(relaxed = true) - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = VpnSettingsDialog.Mtu(mtuEditValue = EMPTY_STRING) - ), - onRestoreMtuClick = mockedClickHandler, - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Act - composeTestRule.onNodeWithText("Reset to default").performClick() - - // Assert - verify { mockedClickHandler.invoke() } - } - - @Test - fun testMtuDialogCancelClick() { - // Arrange - val mockedClickHandler: () -> Unit = mockk(relaxed = true) - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = VpnSettingsDialog.Mtu(mtuEditValue = EMPTY_STRING) - ), - onCancelMtuDialogClick = mockedClickHandler, - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText("Cancel").performClick() - - // Assert - verify { mockedClickHandler.invoke() } - } - - @Test fun testCustomDnsAddressesAndAddButtonVisibleWhenCustomDnsEnabled() { // Arrange composeTestRule.setContentWithTheme { @@ -254,7 +84,6 @@ class VpnSettingsScreenTest { uiState = VpnSettingsUiState.createDefault( isCustomDnsEnabled = true, - isAllowLanEnabled = false, customDnsItems = listOf( CustomDnsItem(address = DUMMY_DNS_ADDRESS, false), @@ -262,7 +91,6 @@ class VpnSettingsScreenTest { CustomDnsItem(address = DUMMY_DNS_ADDRESS_3, false) ) ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() ) } @@ -285,7 +113,6 @@ class VpnSettingsScreenTest { isCustomDnsEnabled = false, customDnsItems = listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, false)) ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() ) } composeTestRule @@ -304,11 +131,10 @@ class VpnSettingsScreenTest { uiState = VpnSettingsUiState.createDefault( isCustomDnsEnabled = true, - isAllowLanEnabled = true, + isLocalNetworkSharingEnabled = true, customDnsItems = listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = true)) ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() ) } @@ -324,11 +150,9 @@ class VpnSettingsScreenTest { uiState = VpnSettingsUiState.createDefault( isCustomDnsEnabled = true, - isAllowLanEnabled = false, customDnsItems = listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = false)) ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() ) } @@ -344,11 +168,9 @@ class VpnSettingsScreenTest { uiState = VpnSettingsUiState.createDefault( isCustomDnsEnabled = true, - isAllowLanEnabled = true, customDnsItems = listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = false)) ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() ) } @@ -364,11 +186,9 @@ class VpnSettingsScreenTest { uiState = VpnSettingsUiState.createDefault( isCustomDnsEnabled = true, - isAllowLanEnabled = false, customDnsItems = listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = true)) ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() ) } @@ -379,228 +199,12 @@ class VpnSettingsScreenTest { } @Test - fun testClickAddDns() { - // Arrange - val mockedClickHandler: (Int?) -> Unit = mockk(relaxed = true) - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = VpnSettingsUiState.createDefault(isCustomDnsEnabled = true), - onDnsClick = mockedClickHandler, - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Act - composeTestRule.onNodeWithText("Add a server").performClick() - - // Assert - verify { mockedClickHandler.invoke(null) } - } - - @Test - fun testShowDnsDialogForNewDnsServer() { - // Arrange - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = - VpnSettingsDialog.Dns( - stagedDns = - StagedDns.NewDns( - item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false) - ), - ) - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText("Add DNS server").assertExists() - } - - @Test - fun testShowDnsDialogForUpdatingDnsServer() { - // Arrange - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = - VpnSettingsDialog.Dns( - stagedDns = - StagedDns.EditDns( - item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false), - index = 0 - ) - ) - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText("Update DNS server").assertExists() - } - - @Test - fun testDnsDialogLanWarningShownWhenLanTrafficDisabledAndLocalAddressUsed() { - // Arrange - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = - VpnSettingsDialog.Dns( - stagedDns = - StagedDns.NewDns( - item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = true), - validationResult = StagedDns.ValidationResult.Success - ), - ), - isAllowLanEnabled = false - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertExists() - } - - @Test - fun testDnsDialogLanWarningNotShownWhenLanTrafficEnabledAndLocalAddressUsed() { - // Arrange - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = - VpnSettingsDialog.Dns( - stagedDns = - StagedDns.NewDns( - item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = true), - validationResult = StagedDns.ValidationResult.Success - ), - ), - isAllowLanEnabled = true - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist() - } - - @Test - fun testDnsDialogLanWarningNotShownWhenLanTrafficEnabledAndNonLocalAddressUsed() { - // Arrange - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = - VpnSettingsDialog.Dns( - stagedDns = - StagedDns.NewDns( - item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false), - validationResult = StagedDns.ValidationResult.Success - ), - ), - isAllowLanEnabled = true - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist() - } - - @Test - fun testDnsDialogLanWarningNotShownWhenLanTrafficDisabledAndNonLocalAddressUsed() { - // Arrange - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = - VpnSettingsDialog.Dns( - stagedDns = - StagedDns.NewDns( - item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false), - validationResult = StagedDns.ValidationResult.Success - ), - ), - isAllowLanEnabled = false - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist() - } - - @Test - fun testDnsDialogSubmitButtonDisabledOnInvalidDnsAddress() { - // Arrange - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = - VpnSettingsDialog.Dns( - stagedDns = - StagedDns.NewDns( - item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false), - validationResult = StagedDns.ValidationResult.InvalidAddress - ) - ) - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText("Submit").assertIsNotEnabled() - } - - @Test - fun testDnsDialogSubmitButtonDisabledOnDuplicateDnsAddress() { - // Arrange - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = - VpnSettingsDialog.Dns( - stagedDns = - StagedDns.NewDns( - item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false), - validationResult = - StagedDns.ValidationResult.DuplicateAddress - ) - ), - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText("Submit").assertIsNotEnabled() - } - - @Test fun testShowSelectedTunnelQuantumOption() { // Arrange composeTestRule.setContentWithTheme { VpnSettingsScreen( uiState = VpnSettingsUiState.createDefault(quantumResistant = QuantumResistantState.On), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() ) } composeTestRule @@ -624,8 +228,7 @@ class VpnSettingsScreenTest { VpnSettingsUiState.createDefault( quantumResistant = QuantumResistantState.Auto, ), - onSelectQuantumResistanceSetting = mockSelectQuantumResistantSettingListener, - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() + onSelectQuantumResistanceSetting = mockSelectQuantumResistantSettingListener ) } composeTestRule @@ -642,23 +245,6 @@ class VpnSettingsScreenTest { } @Test - fun testShowTunnelQuantumInfo() { - // Arrange - composeTestRule.setContentWithTheme { - VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - dialog = VpnSettingsDialog.QuantumResistanceInfo - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() - ) - } - - // Assert - composeTestRule.onNodeWithText("Got it!").assertExists() - } - - @Test fun testShowWireguardPortOptions() { // Arrange composeTestRule.setContentWithTheme { @@ -667,7 +253,6 @@ class VpnSettingsScreenTest { VpnSettingsUiState.createDefault( selectedWireguardPort = Constraint.Only(Port(53)) ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() ) } @@ -698,8 +283,7 @@ class VpnSettingsScreenTest { VpnSettingsUiState.createDefault( selectedWireguardPort = Constraint.Only(Port(53)) ), - onWireguardPortSelected = mockSelectWireguardPortSelectionListener, - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() + onWireguardPortSelected = mockSelectWireguardPortSelectionListener ) } @@ -723,132 +307,163 @@ class VpnSettingsScreenTest { } @Test - fun testShowWireguardPortInfo() { + fun testShowWireguardCustomPort() { // Arrange composeTestRule.setContentWithTheme { VpnSettingsScreen( uiState = VpnSettingsUiState.createDefault( - dialog = - VpnSettingsDialog.WireguardPortInfo( - availablePortRanges = listOf(PortRange(53, 53), PortRange(120, 121)) - ) + customWireguardPort = Constraint.Only(Port(4000)) ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() ) } - // Assert + // Act composeTestRule - .onNodeWithText( - "The automatic setting will randomly choose from the valid port ranges shown below." - ) - .assertExists() + .onNodeWithTag(LAZY_LIST_TEST_TAG) + .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG)) + + // Assert + composeTestRule.onNodeWithText("4000").assertExists() } @Test - fun testShowWireguardCustomPortDialog() { + fun testSelectWireguardCustomPort() { // Arrange + val onWireguardPortSelected: (Constraint<Port>) -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { VpnSettingsScreen( uiState = VpnSettingsUiState.createDefault( - dialog = - VpnSettingsDialog.CustomPort( - availablePortRanges = listOf(PortRange(53, 53), PortRange(120, 121)) - ) + selectedWireguardPort = Constraint.Only(Port(4000)), + customWireguardPort = Constraint.Only(Port(4000)) ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() + onWireguardPortSelected = onWireguardPortSelected ) } + // Act + composeTestRule + .onNodeWithTag(LAZY_LIST_TEST_TAG) + .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG)) + composeTestRule + .onNodeWithTag(testTag = LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG) + .performClick() + // Assert - composeTestRule.onNodeWithText("Valid ranges: 53, 120-121").assertExists() + verify { onWireguardPortSelected.invoke(Constraint.Only(Port(4000))) } } + // Navigation Tests + @Test - fun testShowWireguardCustomPort() { + fun testMtuClick() { // Arrange + val mockedClickHandler: (Int?) -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - selectedWireguardPort = Constraint.Only(Port(4000)) - ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() + uiState = VpnSettingsUiState.createDefault(), + navigateToMtuDialog = mockedClickHandler ) } - // Act composeTestRule .onNodeWithTag(LAZY_LIST_TEST_TAG) - .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG)) + .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG)) + + // Act + composeTestRule.onNodeWithText("WireGuard MTU").performClick() // Assert - composeTestRule.onNodeWithText("4000").assertExists() + verify { mockedClickHandler.invoke(null) } } @Test - fun testClickWireguardCustomPortMainCell() { + fun testClickAddDns() { + // Arrange + val mockedClickHandler: (Int?, String?) -> Unit = mockk(relaxed = true) + composeTestRule.setContentWithTheme { + VpnSettingsScreen( + uiState = VpnSettingsUiState.createDefault(isCustomDnsEnabled = true), + navigateToDns = mockedClickHandler + ) + } + + // Act + composeTestRule.onNodeWithText("Add a server").performClick() + + // Assert + verify { mockedClickHandler.invoke(null, null) } + } + + @Test + fun testShowTunnelQuantumInfo() { + val mockedShowTunnelQuantumInfoClick: () -> Unit = mockk(relaxed = true) + // Arrange - val mockOnShowCustomPortDialog: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { VpnSettingsScreen( uiState = VpnSettingsUiState.createDefault(), - onShowCustomPortDialog = mockOnShowCustomPortDialog, - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() + navigateToQuantumResistanceInfo = mockedShowTunnelQuantumInfoClick ) } // Act composeTestRule .onNodeWithTag(LAZY_LIST_TEST_TAG) - .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG)) - composeTestRule.onNodeWithTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG).performClick() + .performScrollToNode(hasTestTag(LAZY_LIST_QUANTUM_ITEM_ON_TEST_TAG)) + composeTestRule.onNodeWithText("Quantum-resistant tunnel").performClick() // Assert - verify { mockOnShowCustomPortDialog.invoke() } + verify(exactly = 1) { mockedShowTunnelQuantumInfoClick() } } @Test - fun testClickWireguardCustomPortNumberCell() { + fun testShowWireguardPortInfo() { + val mockedClickHandler: (List<PortRange>) -> Unit = mockk(relaxed = true) + // Arrange - val mockOnShowCustomPortDialog: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - selectedWireguardPort = Constraint.Only(Port(4000)) - ), - onShowCustomPortDialog = mockOnShowCustomPortDialog, - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() + uiState = VpnSettingsUiState.createDefault(), + navigateToWireguardPortInfo = mockedClickHandler + ) + } + + composeTestRule.onNodeWithText("WireGuard port").performClick() + + verify(exactly = 1) { mockedClickHandler.invoke(any()) } + } + + @Test + fun testShowWireguardCustomPortDialog() { + val mockedClickHandler: () -> Unit = mockk(relaxed = true) + + // Arrange + composeTestRule.setContentWithTheme { + VpnSettingsScreen( + uiState = VpnSettingsUiState.createDefault(), + navigateToWireguardPortDialog = mockedClickHandler ) } - // Act composeTestRule .onNodeWithTag(LAZY_LIST_TEST_TAG) - .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG)) - composeTestRule - .onNodeWithTag(testTag = LAZY_LIST_WIREGUARD_CUSTOM_PORT_NUMBER_TEST_TAG) - .performClick() + .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_NUMBER_TEST_TAG)) + composeTestRule.onNodeWithText("Custom").performClick() // Assert - verify { mockOnShowCustomPortDialog.invoke() } + verify(exactly = 1) { mockedClickHandler.invoke() } } @Test - fun testSelectWireguardCustomPort() { + fun testClickWireguardCustomPortMainCell() { // Arrange - val onWireguardPortSelected: (Constraint<Port>) -> Unit = mockk(relaxed = true) + val mockOnShowCustomPortDialog: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { VpnSettingsScreen( - uiState = - VpnSettingsUiState.createDefault( - selectedWireguardPort = Constraint.Only(Port(4000)) - ), - onWireguardPortSelected = onWireguardPortSelected, - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() + uiState = VpnSettingsUiState.createDefault(), + navigateToWireguardPortDialog = mockOnShowCustomPortDialog ) } @@ -856,51 +471,43 @@ class VpnSettingsScreenTest { composeTestRule .onNodeWithTag(LAZY_LIST_TEST_TAG) .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG)) - composeTestRule - .onNodeWithTag(testTag = LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG) - .performClick() + composeTestRule.onNodeWithTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG).performClick() // Assert - verify { onWireguardPortSelected.invoke(Constraint.Only(Port(4000))) } + verify { mockOnShowCustomPortDialog.invoke() } } @Test - fun testShowWireguardCustomPortDialogInvalidInt() { - // Input a number to make sure that a too long number does not show and it does not crash - // the app - + fun testClickWireguardCustomPortNumberCell() { // Arrange + val mockOnShowCustomPortDialog: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { VpnSettingsScreen( uiState = VpnSettingsUiState.createDefault( - dialog = - VpnSettingsDialog.CustomPort( - availablePortRanges = listOf(PortRange(53, 53), PortRange(120, 121)) - ) + selectedWireguardPort = Constraint.Only(Port(4000)) ), - toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow() + navigateToWireguardPortDialog = mockOnShowCustomPortDialog ) } // Act composeTestRule - .onNodeWithTag(CUSTOM_PORT_DIALOG_INPUT_TEST_TAG) - .performTextInput("21474836471") + .onNodeWithTag(LAZY_LIST_TEST_TAG) + .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG)) + composeTestRule + .onNodeWithTag(testTag = LAZY_LIST_WIREGUARD_CUSTOM_PORT_NUMBER_TEST_TAG) + .performClick() // Assert - composeTestRule - .onNodeWithTagAndText(CUSTOM_PORT_DIALOG_INPUT_TEST_TAG, "21474836471") - .assertDoesNotExist() + verify { mockOnShowCustomPortDialog.invoke() } } 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" diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt index a54c41c20d..e62b1a399b 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt @@ -1,6 +1,5 @@ package net.mullvad.mullvadvpn.compose.screen -import android.app.Activity import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText @@ -9,9 +8,6 @@ import io.mockk.MockKAnnotations import io.mockk.every import io.mockk.mockk import io.mockk.verify -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asSharedFlow import net.mullvad.mullvadvpn.compose.setContentWithTheme import net.mullvad.mullvadvpn.compose.state.PaymentState import net.mullvad.mullvadvpn.compose.state.WelcomeUiState @@ -20,9 +16,6 @@ import net.mullvad.mullvadvpn.lib.payment.model.PaymentProduct import net.mullvad.mullvadvpn.lib.payment.model.PaymentStatus import net.mullvad.mullvadvpn.lib.payment.model.ProductId import net.mullvad.mullvadvpn.lib.payment.model.ProductPrice -import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult -import net.mullvad.mullvadvpn.util.toPaymentDialogData -import net.mullvad.mullvadvpn.viewmodel.WelcomeViewModel import org.junit.Before import org.junit.Rule import org.junit.Test @@ -40,16 +33,14 @@ class WelcomeScreenTest { // Arrange composeTestRule.setContentWithTheme { WelcomeScreen( - showSitePayment = true, uiState = WelcomeUiState(), - uiSideEffect = MutableSharedFlow(), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} + navigateToDeviceInfoDialog = {}, + onPurchaseBillingProductClick = { _ -> }, + navigateToVerificationPendingDialog = {} ) } @@ -65,16 +56,14 @@ class WelcomeScreenTest { // Arrange composeTestRule.setContentWithTheme { WelcomeScreen( - showSitePayment = false, uiState = WelcomeUiState(), - uiSideEffect = MutableSharedFlow(), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} + navigateToDeviceInfoDialog = {}, + onPurchaseBillingProductClick = { _ -> }, + navigateToVerificationPendingDialog = {} ) } @@ -96,16 +85,14 @@ class WelcomeScreenTest { val expectedAccountNumber = "1111 2222 3333 4444" composeTestRule.setContentWithTheme { WelcomeScreen( - showSitePayment = true, uiState = WelcomeUiState(accountNumber = rawAccountNumber), - uiSideEffect = MutableSharedFlow(), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} + onPurchaseBillingProductClick = { _ -> }, + navigateToDeviceInfoDialog = {}, + navigateToVerificationPendingDialog = {} ) } @@ -114,67 +101,19 @@ class WelcomeScreenTest { } @Test - fun testOpenAccountView() { - // Arrange - composeTestRule.setContentWithTheme { - WelcomeScreen( - showSitePayment = true, - uiState = WelcomeUiState(), - uiSideEffect = - MutableStateFlow(WelcomeViewModel.UiSideEffect.OpenAccountView("222")), - onSitePaymentClick = {}, - onRedeemVoucherClick = {}, - onSettingsClick = {}, - onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} - ) - } - - // Assert - composeTestRule.apply { onNodeWithText("Congrats!").assertDoesNotExist() } - } - - @Test - fun testOpenConnectScreen() { - // Arrange - val mockClickListener: () -> Unit = mockk(relaxed = true) - composeTestRule.setContentWithTheme { - WelcomeScreen( - showSitePayment = true, - uiState = WelcomeUiState(), - uiSideEffect = MutableStateFlow(WelcomeViewModel.UiSideEffect.OpenConnectScreen), - onSitePaymentClick = {}, - onRedeemVoucherClick = {}, - onSettingsClick = {}, - onAccountClick = {}, - openConnectScreen = mockClickListener, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} - ) - } - - // Assert - verify(exactly = 1) { mockClickListener.invoke() } - } - - @Test fun testClickSitePaymentButton() { // Arrange val mockClickListener: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { WelcomeScreen( - showSitePayment = true, - uiState = WelcomeUiState(), - uiSideEffect = MutableStateFlow(WelcomeViewModel.UiSideEffect.OpenConnectScreen), + uiState = WelcomeUiState(showSitePayment = true), onSitePaymentClick = mockClickListener, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} + onPurchaseBillingProductClick = { _ -> }, + navigateToVerificationPendingDialog = {}, + navigateToDeviceInfoDialog = {} ) } @@ -191,16 +130,14 @@ class WelcomeScreenTest { val mockClickListener: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { WelcomeScreen( - showSitePayment = true, uiState = WelcomeUiState(), - uiSideEffect = MutableStateFlow(WelcomeViewModel.UiSideEffect.OpenConnectScreen), onSitePaymentClick = {}, onRedeemVoucherClick = mockClickListener, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} + onPurchaseBillingProductClick = { _ -> }, + navigateToVerificationPendingDialog = {}, + navigateToDeviceInfoDialog = {} ) } @@ -212,99 +149,18 @@ class WelcomeScreenTest { } @Test - fun testShowPurchaseCompleteDialog() { - // Arrange - composeTestRule.setContentWithTheme { - WelcomeScreen( - showSitePayment = true, - uiState = - WelcomeUiState( - paymentDialogData = PurchaseResult.Completed.Success.toPaymentDialogData() - ), - uiSideEffect = MutableStateFlow(WelcomeViewModel.UiSideEffect.OpenConnectScreen), - onSitePaymentClick = {}, - onRedeemVoucherClick = {}, - onSettingsClick = {}, - onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} - ) - } - - // Assert - composeTestRule.onNodeWithText("Time was successfully added").assertExists() - } - - @Test - fun testShowVerificationErrorDialog() { - // Arrange - composeTestRule.setContentWithTheme { - WelcomeScreen( - showSitePayment = true, - uiState = - WelcomeUiState( - paymentDialogData = - PurchaseResult.Error.VerificationError(null).toPaymentDialogData() - ), - uiSideEffect = MutableStateFlow(WelcomeViewModel.UiSideEffect.OpenConnectScreen), - onSitePaymentClick = {}, - onRedeemVoucherClick = {}, - onSettingsClick = {}, - onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} - ) - } - - // Assert - composeTestRule.onNodeWithText("Verifying purchase").assertExists() - } - - @Test - fun testShowFetchProductsErrorDialog() { - // Arrange - composeTestRule.setContentWithTheme { - WelcomeScreen( - showSitePayment = true, - uiState = - WelcomeUiState() - .copy( - paymentDialogData = - PurchaseResult.Error.FetchProductsError(ProductId(""), null) - .toPaymentDialogData() - ), - uiSideEffect = MutableSharedFlow<WelcomeViewModel.UiSideEffect>().asSharedFlow(), - onSitePaymentClick = {}, - onRedeemVoucherClick = {}, - onSettingsClick = {}, - onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} - ) - } - - // Assert - composeTestRule.onNodeWithText("Google Play unavailable").assertExists() - } - - @Test fun testShowBillingErrorPaymentButton() { // Arrange composeTestRule.setContentWithTheme { WelcomeScreen( - showSitePayment = true, uiState = WelcomeUiState().copy(billingPaymentState = PaymentState.Error.Billing), - uiSideEffect = MutableSharedFlow<WelcomeViewModel.UiSideEffect>().asSharedFlow(), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, - onClosePurchaseResultDialog = {}, - onPurchaseBillingProductClick = { _, _ -> } + onPurchaseBillingProductClick = { _ -> }, + navigateToVerificationPendingDialog = {}, + navigateToDeviceInfoDialog = {} ) } @@ -320,20 +176,18 @@ class WelcomeScreenTest { every { mockPaymentProduct.status } returns null composeTestRule.setContentWithTheme { WelcomeScreen( - showSitePayment = true, uiState = WelcomeUiState( billingPaymentState = PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) ), - uiSideEffect = MutableStateFlow(WelcomeViewModel.UiSideEffect.OpenConnectScreen), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} + onPurchaseBillingProductClick = { _ -> }, + navigateToVerificationPendingDialog = {}, + navigateToDeviceInfoDialog = {} ) } @@ -349,21 +203,19 @@ class WelcomeScreenTest { every { mockPaymentProduct.status } returns PaymentStatus.PENDING composeTestRule.setContentWithTheme { WelcomeScreen( - showSitePayment = true, uiState = WelcomeUiState() .copy( billingPaymentState = PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) ), - uiSideEffect = MutableSharedFlow<WelcomeViewModel.UiSideEffect>().asSharedFlow(), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} + onPurchaseBillingProductClick = { _ -> }, + navigateToVerificationPendingDialog = {}, + navigateToDeviceInfoDialog = {} ) } @@ -377,23 +229,22 @@ class WelcomeScreenTest { val mockPaymentProduct: PaymentProduct = mockk() every { mockPaymentProduct.price } returns ProductPrice("$10") every { mockPaymentProduct.status } returns PaymentStatus.PENDING + val mockShowPendingInfo = mockk<() -> Unit>(relaxed = true) composeTestRule.setContentWithTheme { WelcomeScreen( - showSitePayment = true, uiState = WelcomeUiState() .copy( billingPaymentState = PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) ), - uiSideEffect = MutableSharedFlow<WelcomeViewModel.UiSideEffect>().asSharedFlow(), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} + onPurchaseBillingProductClick = { _ -> }, + navigateToVerificationPendingDialog = mockShowPendingInfo, + navigateToDeviceInfoDialog = {} ) } @@ -401,11 +252,7 @@ class WelcomeScreenTest { composeTestRule.onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).performClick() // Assert - composeTestRule - .onNodeWithText( - "We are currently verifying your purchase, this might take some time. Your time will be added if the verification is successful." - ) - .assertExists() + verify(exactly = 1) { mockShowPendingInfo() } } @Test @@ -416,21 +263,19 @@ class WelcomeScreenTest { every { mockPaymentProduct.status } returns PaymentStatus.VERIFICATION_IN_PROGRESS composeTestRule.setContentWithTheme { WelcomeScreen( - showSitePayment = true, uiState = WelcomeUiState() .copy( billingPaymentState = PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) ), - uiSideEffect = MutableSharedFlow<WelcomeViewModel.UiSideEffect>().asSharedFlow(), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, - onPurchaseBillingProductClick = { _, _ -> }, - onClosePurchaseResultDialog = {} + onPurchaseBillingProductClick = { _ -> }, + navigateToVerificationPendingDialog = {}, + navigateToDeviceInfoDialog = {} ) } @@ -441,27 +286,25 @@ class WelcomeScreenTest { @Test fun testOnPurchaseBillingProductClick() { // Arrange - val clickHandler: (ProductId, () -> Activity) -> Unit = mockk(relaxed = true) + val clickHandler: (ProductId) -> Unit = mockk(relaxed = true) val mockPaymentProduct: PaymentProduct = mockk() every { mockPaymentProduct.price } returns ProductPrice("$10") every { mockPaymentProduct.productId } returns ProductId("PRODUCT_ID") every { mockPaymentProduct.status } returns null composeTestRule.setContentWithTheme { WelcomeScreen( - showSitePayment = true, uiState = WelcomeUiState( billingPaymentState = PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) ), - uiSideEffect = MutableStateFlow(WelcomeViewModel.UiSideEffect.OpenConnectScreen), onSitePaymentClick = {}, onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {}, onPurchaseBillingProductClick = clickHandler, - onClosePurchaseResultDialog = {} + navigateToVerificationPendingDialog = {}, + navigateToDeviceInfoDialog = {} ) } @@ -469,6 +312,6 @@ class WelcomeScreenTest { composeTestRule.onNodeWithText("Add 30 days time ($10)").performClick() // Assert - verify { clickHandler(ProductId("PRODUCT_ID"), any()) } + verify { clickHandler(ProductId("PRODUCT_ID")) } } } |
