summaryrefslogtreecommitdiffhomepage
path: root/android/app/src
diff options
context:
space:
mode:
authorJonatan Rhodin <jonatan.rhodin@mullvad.net>2023-11-16 01:00:20 +0100
committerJonatan Rhodin <jonatan.rhodin@mullvad.net>2023-11-16 09:34:26 +0100
commit06a950f5982d0d56031803a6d96a7bce6701bc08 (patch)
treeb61f1c95d2d1377629f67233d3a0a24471f06a98 /android/app/src
parent91a030a18450c5b7bc531544c54df0445746f1fa (diff)
downloadmullvadvpn-06a950f5982d0d56031803a6d96a7bce6701bc08.tar.xz
mullvadvpn-06a950f5982d0d56031803a6d96a7bce6701bc08.zip
Add payment unit tests for AccountViewModel
Diffstat (limited to 'android/app/src')
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt141
1 files changed, 137 insertions, 4 deletions
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt
index fc1fd5e99b..c02e755951 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt
@@ -1,15 +1,27 @@
package net.mullvad.mullvadvpn.viewmodel
+import android.app.Activity
import app.cash.turbine.test
+import io.mockk.coEvery
+import io.mockk.coVerify
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.unmockkAll
import io.mockk.verify
import kotlin.test.assertEquals
+import kotlin.test.assertIs
+import kotlin.test.assertNull
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
+import net.mullvad.mullvadvpn.compose.dialog.payment.PaymentDialogData
+import net.mullvad.mullvadvpn.compose.state.PaymentState
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
+import net.mullvad.mullvadvpn.lib.common.test.assertLists
+import net.mullvad.mullvadvpn.lib.payment.model.PaymentAvailability
+import net.mullvad.mullvadvpn.lib.payment.model.PaymentProduct
+import net.mullvad.mullvadvpn.lib.payment.model.ProductId
+import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult
import net.mullvad.mullvadvpn.model.AccountAndDevice
import net.mullvad.mullvadvpn.model.AccountExpiry
import net.mullvad.mullvadvpn.model.Device
@@ -19,6 +31,8 @@ import net.mullvad.mullvadvpn.repository.DeviceRepository
import net.mullvad.mullvadvpn.ui.serviceconnection.AuthTokenCache
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.ui.serviceconnection.authTokenCache
+import net.mullvad.mullvadvpn.usecase.PaymentUseCase
+import net.mullvad.mullvadvpn.util.toPaymentDialogData
import org.junit.After
import org.junit.Before
import org.junit.Rule
@@ -31,8 +45,11 @@ class AccountViewModelTest {
private val mockServiceConnectionManager: ServiceConnectionManager = mockk()
private val mockDeviceRepository: DeviceRepository = mockk()
private val mockAuthTokenCache: AuthTokenCache = mockk()
+ private val mockPaymentUseCase: PaymentUseCase = mockk(relaxed = true)
private val deviceState: MutableStateFlow<DeviceState> = MutableStateFlow(DeviceState.Initial)
+ private val paymentAvailability = MutableStateFlow<PaymentAvailability?>(null)
+ private val purchaseResult = MutableStateFlow<PurchaseResult?>(null)
private val accountExpiryState = MutableStateFlow(AccountExpiry.Missing)
private val dummyAccountAndDevice: AccountAndDevice =
@@ -51,15 +68,19 @@ class AccountViewModelTest {
@Before
fun setUp() {
mockkStatic(CACHE_EXTENSION_CLASS)
+ mockkStatic(PURCHASE_RESULT_EXTENSIONS_CLASS)
every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache
every { mockDeviceRepository.deviceState } returns deviceState
every { mockAccountRepository.accountExpiryState } returns accountExpiryState
+ coEvery { mockPaymentUseCase.purchaseResult } returns purchaseResult
+ coEvery { mockPaymentUseCase.paymentAvailability } returns paymentAvailability
viewModel =
AccountViewModel(
accountRepository = mockAccountRepository,
serviceConnectionManager = mockServiceConnectionManager,
- deviceRepository = mockDeviceRepository
+ deviceRepository = mockDeviceRepository,
+ paymentUseCase = mockPaymentUseCase
)
}
@@ -72,10 +93,9 @@ class AccountViewModelTest {
fun testAccountLoggedInState() = runTest {
// Act, Assert
viewModel.uiState.test {
- var result = awaitItem()
- assertEquals(null, result.deviceName)
+ awaitItem() // Default state
deviceState.value = DeviceState.LoggedIn(accountAndDevice = dummyAccountAndDevice)
- result = awaitItem()
+ val result = awaitItem()
assertEquals(DUMMY_DEVICE_NAME, result.accountNumber)
}
}
@@ -89,8 +109,121 @@ class AccountViewModelTest {
verify { mockAccountRepository.logout() }
}
+ @Test
+ fun testBillingProductsUnavailableState() = runTest {
+ // Arrange in setup
+
+ // Act, Assert
+ viewModel.uiState.test {
+ awaitItem() // Default state
+ paymentAvailability.tryEmit(PaymentAvailability.ProductsUnavailable)
+ val result = awaitItem().billingPaymentState
+ assertIs<PaymentState.NoPayment>(result)
+ }
+ }
+
+ @Test
+ fun testBillingProductsGenericErrorState() = runTest {
+ // Act, Assert
+ viewModel.uiState.test {
+ awaitItem() // Default state
+ paymentAvailability.tryEmit(PaymentAvailability.Error.Other(mockk()))
+ val result = awaitItem().billingPaymentState
+ assertIs<PaymentState.Error.Generic>(result)
+ }
+ }
+
+ @Test
+ fun testBillingProductsBillingErrorState() = runTest {
+ // Act, Assert
+ viewModel.uiState.test {
+ awaitItem() // Default state
+ paymentAvailability.tryEmit(PaymentAvailability.Error.BillingUnavailable)
+ val result = awaitItem().billingPaymentState
+ assertIs<PaymentState.Error.Billing>(result)
+ }
+ }
+
+ @Test
+ fun testBillingProductsPaymentAvailableState() = runTest {
+ // Arrange
+ val mockProduct: PaymentProduct = mockk()
+ val expectedProductList = listOf(mockProduct)
+
+ // Act, Assert
+ viewModel.uiState.test {
+ awaitItem() // Default state
+ paymentAvailability.tryEmit(PaymentAvailability.ProductsAvailable(listOf(mockProduct)))
+ val result = awaitItem().billingPaymentState
+ assertIs<PaymentState.PaymentAvailable>(result)
+ assertLists(expectedProductList, result.products)
+ }
+ }
+
+ @Test
+ fun testBillingUserCancelled() = runTest {
+ // Arrange
+ val result = PurchaseResult.Completed.Cancelled
+ purchaseResult.value = result
+ every { result.toPaymentDialogData() } returns null
+
+ // Act, Assert
+ viewModel.uiState.test { assertNull(awaitItem().paymentDialogData) }
+ }
+
+ @Test
+ fun testBillingPurchaseSuccess() = runTest {
+ // Arrange
+ val result = PurchaseResult.Completed.Success
+ val expectedData: PaymentDialogData = mockk()
+ purchaseResult.value = result
+ every { result.toPaymentDialogData() } returns expectedData
+
+ // Act, Assert
+ viewModel.uiState.test { assertEquals(expectedData, awaitItem().paymentDialogData) }
+ }
+
+ @Test
+ fun testStartBillingPayment() {
+ // Arrange
+ val mockProductId = ProductId("MOCK")
+ val mockActivityProvider = mockk<() -> Activity>()
+
+ // Act
+ viewModel.startBillingPayment(mockProductId, mockActivityProvider)
+
+ // Assert
+ coVerify { mockPaymentUseCase.purchaseProduct(mockProductId, mockActivityProvider) }
+ }
+
+ @Test
+ fun testOnClosePurchaseResultDialogSuccessful() {
+ // Arrange
+
+ // Act
+ viewModel.onClosePurchaseResultDialog(success = true)
+
+ // Assert
+ verify { mockAccountRepository.fetchAccountExpiry() }
+ coVerify { mockPaymentUseCase.resetPurchaseResult() }
+ }
+
+ @Test
+ fun testOnClosePurchaseResultDialogNotSuccessful() {
+ // Arrange
+
+ // Act
+ viewModel.onClosePurchaseResultDialog(success = false)
+
+ // Assert
+ coVerify { mockPaymentUseCase.queryPaymentAvailability() }
+ coVerify { mockPaymentUseCase.resetPurchaseResult() }
+ }
+
companion object {
private const val CACHE_EXTENSION_CLASS = "net.mullvad.mullvadvpn.util.CacheExtensionsKt"
+ private const val PURCHASE_RESULT_EXTENSIONS_CLASS =
+ "net.mullvad.mullvadvpn.util.PurchaseResultExtensionsKt"
private const val DUMMY_DEVICE_NAME = "fake_name"
}
}