summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorDavid Göransson <david.goransson@mullvad.net>2025-07-09 16:14:17 +0200
committerDavid Göransson <david.goransson@mullvad.net>2025-07-09 16:14:17 +0200
commit4d90ff4fd81b0692945df0c67e0e8074716c14f3 (patch)
treedc54697af312d65ff246d0fc3c07d5a44fd524af /android
parentab2cf79c4b36e7ecf0485e57c89b50738b4fc482 (diff)
parentb1020e692b5cb4dfefb77a75c34d4f6af569d41e (diff)
downloadmullvadvpn-4d90ff4fd81b0692945df0c67e0e8074716c14f3.tar.xz
mullvadvpn-4d90ff4fd81b0692945df0c67e0e8074716c14f3.zip
Merge branch 'billing-tests-are-flaky-droid-2075'
Diffstat (limited to 'android')
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/component/AddTimeBottomSheetTest.kt50
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/AddMoreTimeUiStatePreviewParameterProvider.kt4
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AddTimeUiState.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AddTimeViewModel.kt5
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AddTimeViewModelTest.kt33
5 files changed, 67 insertions, 27 deletions
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/component/AddTimeBottomSheetTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/component/AddTimeBottomSheetTest.kt
index 095c15dafc..893ac23825 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/component/AddTimeBottomSheetTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/component/AddTimeBottomSheetTest.kt
@@ -78,7 +78,7 @@ class AddTimeBottomSheetTest {
state =
AddTimeUiState(
purchaseState = null,
- billingPaymentState = null,
+ billingPaymentState = PaymentState.NoPayment,
showSitePayment = true,
tunnelStateBlocked = false,
)
@@ -102,7 +102,7 @@ class AddTimeBottomSheetTest {
state =
AddTimeUiState(
purchaseState = null,
- billingPaymentState = null,
+ billingPaymentState = PaymentState.NoPayment,
tunnelStateBlocked = false,
showSitePayment = true,
)
@@ -271,12 +271,21 @@ class AddTimeBottomSheetTest {
fun testShowPurchaseCompleteDialog() =
composeExtension.use {
// Arrange
+ val productId = ProductId(ProductIds.ThreeMonths)
initBottomSheet(
state =
AddTimeUiState(
- purchaseState =
- PurchaseState.Success(ProductId(ProductIds.ThreeMonths)),
- billingPaymentState = null,
+ purchaseState = PurchaseState.Success(productId),
+ billingPaymentState =
+ PaymentState.PaymentAvailable(
+ listOf(
+ PaymentProduct(
+ productId = productId,
+ price = ProductPrice("$30"),
+ status = null,
+ )
+ )
+ ),
tunnelStateBlocked = false,
showSitePayment = false,
)
@@ -292,10 +301,20 @@ class AddTimeBottomSheetTest {
fun testShowVerificationErrorDialog() =
composeExtension.use {
// Arrange
+ val productId = ProductId(ProductIds.ThreeMonths)
initBottomSheet(
AddTimeUiState(
purchaseState = PurchaseState.VerifyingPurchase,
- billingPaymentState = null,
+ billingPaymentState =
+ PaymentState.PaymentAvailable(
+ listOf(
+ PaymentProduct(
+ productId = productId,
+ price = ProductPrice("$30"),
+ status = null,
+ )
+ )
+ ),
tunnelStateBlocked = false,
showSitePayment = false,
)
@@ -310,11 +329,22 @@ class AddTimeBottomSheetTest {
fun testShowFetchProductsErrorDialog() =
composeExtension.use {
// Arrange
+
+ val productId = ProductId(ProductIds.ThreeMonths)
initBottomSheet(
state =
AddTimeUiState(
- purchaseState = PurchaseState.Error.OtherError(ProductId("ProductId")),
- billingPaymentState = null,
+ purchaseState = PurchaseState.Error.OtherError(productId),
+ billingPaymentState =
+ PaymentState.PaymentAvailable(
+ listOf(
+ PaymentProduct(
+ productId = productId,
+ price = ProductPrice("$30"),
+ status = null,
+ )
+ )
+ ),
tunnelStateBlocked = false,
showSitePayment = false,
)
@@ -336,7 +366,7 @@ class AddTimeBottomSheetTest {
state =
AddTimeUiState(
purchaseState = null,
- billingPaymentState = null,
+ billingPaymentState = PaymentState.NoPayment,
tunnelStateBlocked = false,
showSitePayment = false,
)
@@ -355,7 +385,7 @@ class AddTimeBottomSheetTest {
state =
AddTimeUiState(
purchaseState = null,
- billingPaymentState = null,
+ billingPaymentState = PaymentState.NoPayment,
tunnelStateBlocked = true,
showSitePayment = true,
)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/AddMoreTimeUiStatePreviewParameterProvider.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/AddMoreTimeUiStatePreviewParameterProvider.kt
index 1a2f5a7024..24160aa40c 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/AddMoreTimeUiStatePreviewParameterProvider.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/AddMoreTimeUiStatePreviewParameterProvider.kt
@@ -17,14 +17,14 @@ class AddMoreTimeUiStatePreviewParameterProvider :
Lc.Loading(Unit),
AddTimeUiState(
purchaseState = null,
- billingPaymentState = null,
+ billingPaymentState = PaymentState.Loading,
showSitePayment = true,
tunnelStateBlocked = false,
)
.toLc(),
AddTimeUiState(
purchaseState = null,
- billingPaymentState = null,
+ billingPaymentState = PaymentState.NoPayment,
showSitePayment = true,
tunnelStateBlocked = false,
)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AddTimeUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AddTimeUiState.kt
index a9b4d3c09c..94340e8e45 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AddTimeUiState.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AddTimeUiState.kt
@@ -4,7 +4,7 @@ import net.mullvad.mullvadvpn.lib.payment.model.ProductId
data class AddTimeUiState(
val purchaseState: PurchaseState?,
- val billingPaymentState: PaymentState?,
+ val billingPaymentState: PaymentState,
val showSitePayment: Boolean,
val tunnelStateBlocked: Boolean,
)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AddTimeViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AddTimeViewModel.kt
index 141e854b81..36e6864a80 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AddTimeViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AddTimeViewModel.kt
@@ -8,6 +8,7 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
@@ -35,14 +36,14 @@ class AddTimeViewModel(
val uiState: StateFlow<Lc<Unit, AddTimeUiState>> =
combine(
- paymentUseCase.paymentAvailability,
+ paymentUseCase.paymentAvailability.filterNotNull(),
paymentUseCase.purchaseResult,
connectionProxy.tunnelState,
) { paymentAvailability, purchaseResult, tunnelState ->
Lc.Content(
AddTimeUiState(
purchaseState = purchaseResult?.toPurchaseState(),
- billingPaymentState = paymentAvailability?.toPaymentState(),
+ billingPaymentState = paymentAvailability.toPaymentState(),
tunnelStateBlocked = tunnelState.isBlocked(),
showSitePayment = !isPlayBuild,
)
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AddTimeViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AddTimeViewModelTest.kt
index 1b9c4a9ef3..f9497bd159 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AddTimeViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AddTimeViewModelTest.kt
@@ -21,6 +21,7 @@ import net.mullvad.mullvadvpn.lib.model.TunnelState
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.ProductPrice
import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult
import net.mullvad.mullvadvpn.lib.payment.model.VerificationResult
import net.mullvad.mullvadvpn.lib.shared.AccountRepository
@@ -78,12 +79,14 @@ class AddTimeViewModelTest {
@Test
fun `when paymentAvailability emits ErrorOther uiState should be null`() = runTest {
- // Arrange
- paymentAvailability.emit(PaymentAvailability.Error.Other(mockk()))
// Act, Assert
viewModel.uiState.test {
awaitItem() // Default state
+
+ // Emit an error with a mock exception
+ paymentAvailability.emit(PaymentAvailability.Error.Other(mockk()))
+
val result = awaitItem()
assertIs<Lc.Content<AddTimeUiState>>(result)
assertIs<PaymentState.Error.Generic>(result.value.billingPaymentState)
@@ -122,7 +125,7 @@ class AddTimeViewModelTest {
}
@Test
- fun `startBillingPayment should invoke purchaseProduct on PaymentUseCase`() {
+ fun `startBillingPayment should invoke purchaseProduct on PaymentUseCase`() = runTest {
// Arrange
val mockProductId = ProductId("MOCK")
val mockActivityProvider = mockk<() -> Activity>()
@@ -149,7 +152,7 @@ class AddTimeViewModelTest {
}
@Test
- fun `purchaseState error should invoke queryPaymentAvailability on PaymentUseCase`() {
+ fun `purchaseState error should invoke queryPaymentAvailability on PaymentUseCase`() = runTest {
// Arrange
val purchaseResultData = PurchaseResult.Error.VerificationError(Throwable())
@@ -161,25 +164,31 @@ class AddTimeViewModelTest {
}
@Test
- fun `resetPurchaseResult with success should invoke resetPurchaseResult on PaymentUseCase`() {
- // Arrange
+ fun `resetPurchaseResult with success should invoke resetPurchaseResult on PaymentUseCase`() =
+ runTest {
+ // Arrange
- // Act
- viewModel.resetPurchaseResult()
+ // Act
+ viewModel.resetPurchaseResult()
- // Assert
- coVerify { mockPaymentUseCase.resetPurchaseResult() }
- }
+ // Assert
+ coVerify { mockPaymentUseCase.resetPurchaseResult() }
+ }
@Test
fun `purchaseResult emitting Success should result in success dialog state`() = runTest {
// Arrange
- val result = PurchaseState.Success(ProductId("one_month"))
+ val productId = ProductId("one_month")
+ val paymentProduct =
+ PaymentProduct(productId = productId, price = ProductPrice("€5.00"), status = null)
+ val result = PurchaseState.Success(productId)
val purchaseResultData = PurchaseResult.Completed.Success(ProductId("one_month"))
// Act, Assert
viewModel.uiState.test {
awaitItem() // Default state
+ paymentAvailability.emit(PaymentAvailability.ProductsAvailable(listOf(paymentProduct)))
+ awaitItem()
purchaseResult.emit(purchaseResultData)
val item = awaitItem()
assertIs<Lc.Content<AddTimeUiState>>(item)