summaryrefslogtreecommitdiffhomepage
path: root/android/lib/billing/src
diff options
context:
space:
mode:
authorDavid Göransson <david.goransson90@gmail.com>2024-02-26 16:58:36 +0100
committerAlbin <albin@mullvad.net>2024-02-27 09:33:31 +0100
commit81ca0ca0ef00e7d6907d2c9a4ce98211f4dd7eff (patch)
treedf3c3c9a259857225554a3ce79c9302c5d769278 /android/lib/billing/src
parentb04a45035cb42501ac81fd4e9202c2cb4abcb162 (diff)
downloadmullvadvpn-81ca0ca0ef00e7d6907d2c9a4ce98211f4dd7eff.tar.xz
mullvadvpn-81ca0ca0ef00e7d6907d2c9a4ce98211f4dd7eff.zip
Implement sentence naming of tests
Diffstat (limited to 'android/lib/billing/src')
-rw-r--r--android/lib/billing/src/androidTest/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt2
-rw-r--r--android/lib/billing/src/main/kotlin/net/mullvad/mullvadvpn/lib/billing/extension/ProductDetailsResultToPaymentAvailability.kt2
-rw-r--r--android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt358
3 files changed, 187 insertions, 175 deletions
diff --git a/android/lib/billing/src/androidTest/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt b/android/lib/billing/src/androidTest/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt
index 386932681d..7ca3219cfb 100644
--- a/android/lib/billing/src/androidTest/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt
+++ b/android/lib/billing/src/androidTest/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt
@@ -52,7 +52,7 @@ class BillingRepositoryTest {
CapturingSlot()
@BeforeEach
- fun setUp() {
+ fun setup() {
mockkStatic(BILLING_CLIENT_CLASS)
mockkStatic(BILLING_CLIENT_KOTLIN_CLASS)
mockkStatic(BILLING_FLOW_PARAMS)
diff --git a/android/lib/billing/src/main/kotlin/net/mullvad/mullvadvpn/lib/billing/extension/ProductDetailsResultToPaymentAvailability.kt b/android/lib/billing/src/main/kotlin/net/mullvad/mullvadvpn/lib/billing/extension/ProductDetailsResultToPaymentAvailability.kt
index 37cc701724..2cb3e1371a 100644
--- a/android/lib/billing/src/main/kotlin/net/mullvad/mullvadvpn/lib/billing/extension/ProductDetailsResultToPaymentAvailability.kt
+++ b/android/lib/billing/src/main/kotlin/net/mullvad/mullvadvpn/lib/billing/extension/ProductDetailsResultToPaymentAvailability.kt
@@ -17,7 +17,7 @@ fun ProductDetailsResult.toPaymentAvailability(
productDetailsList.toPaymentProducts(productIdToPaymentStatus)
)
} else {
- PaymentAvailability.NoProductsFounds
+ PaymentAvailability.NoProductsFound
}
}
BillingClient.BillingResponseCode.BILLING_UNAVAILABLE ->
diff --git a/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt b/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt
index 21e13d5da8..c4d1b04905 100644
--- a/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt
+++ b/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt
@@ -40,7 +40,7 @@ class BillingPaymentRepositoryTest {
private lateinit var paymentRepository: BillingPaymentRepository
@BeforeEach
- fun setUp() {
+ fun setup() {
mockkStatic(PRODUCT_DETAILS_TO_PAYMENT_PRODUCT_EXT)
every { mockBillingRepository.purchaseEvents } returns purchaseEventFlow
@@ -53,7 +53,7 @@ class BillingPaymentRepositoryTest {
}
@Test
- fun testQueryAvailablePaymentProductsAvailable() = runTest {
+ fun `queryPaymentAvailability should return available products when billing is OK`() = runTest {
// Arrange
val expectedProduct: PaymentProduct = mockk()
val mockProduct: ProductDetails = mockk()
@@ -76,45 +76,47 @@ class BillingPaymentRepositoryTest {
}
@Test
- fun testQueryAvailablePaymentProductsUnavailable() = runTest {
- // Arrange
- val mockResult: ProductDetailsResult = mockk()
- every { mockResult.billingResult.responseCode } returns BillingResponseCode.OK
- every { mockResult.productDetailsList } returns emptyList()
- coEvery { mockBillingRepository.queryPurchases() } returns mockk(relaxed = true)
- coEvery { mockBillingRepository.queryProducts(any()) } returns mockResult
+ fun `queryPaymentAvailability should return NoProductsFound when billing is OK with no products `() =
+ runTest {
+ // Arrange
+ val mockResult: ProductDetailsResult = mockk()
+ every { mockResult.billingResult.responseCode } returns BillingResponseCode.OK
+ every { mockResult.productDetailsList } returns emptyList()
+ coEvery { mockBillingRepository.queryPurchases() } returns mockk(relaxed = true)
+ coEvery { mockBillingRepository.queryProducts(any()) } returns mockResult
- // Act, Assert
- paymentRepository.queryPaymentAvailability().test {
- // Loading
- awaitItem()
- val result = awaitItem()
- assertIs<PaymentAvailability.NoProductsFounds>(result)
- awaitComplete()
+ // Act, Assert
+ paymentRepository.queryPaymentAvailability().test {
+ // Loading
+ awaitItem()
+ val result = awaitItem()
+ assertIs<PaymentAvailability.NoProductsFound>(result)
+ awaitComplete()
+ }
}
- }
@Test
- fun testQueryAvailablePaymentBillingUnavailableError() = runTest {
- // Arrange
- val mockResult: ProductDetailsResult = mockk()
- every { mockResult.billingResult.responseCode } returns
- BillingResponseCode.BILLING_UNAVAILABLE
- coEvery { mockBillingRepository.queryPurchases() } returns mockk(relaxed = true)
- coEvery { mockBillingRepository.queryProducts(any()) } returns mockResult
+ fun `queryPaymentAvailability should return BillingUnavailable when billing is Unavailable `() =
+ runTest {
+ // Arrange
+ val mockResult: ProductDetailsResult = mockk()
+ every { mockResult.billingResult.responseCode } returns
+ BillingResponseCode.BILLING_UNAVAILABLE
+ coEvery { mockBillingRepository.queryPurchases() } returns mockk(relaxed = true)
+ coEvery { mockBillingRepository.queryProducts(any()) } returns mockResult
- // Act, Assert
- paymentRepository.queryPaymentAvailability().test {
- // Loading
- awaitItem()
- val result = awaitItem()
- assertIs<PaymentAvailability.Error.BillingUnavailable>(result)
- awaitComplete()
+ // Act, Assert
+ paymentRepository.queryPaymentAvailability().test {
+ // Loading
+ awaitItem()
+ val result = awaitItem()
+ assertIs<PaymentAvailability.Error.BillingUnavailable>(result)
+ awaitComplete()
+ }
}
- }
@Test
- fun testPurchaseBillingProductStartPurchaseFetchProductsError() = runTest {
+ fun `purchaseProduct should return FetchProductsError when billing is Unavailable`() = runTest {
// Arrange
val mockProductId = ProductId("MOCK")
val mockProductDetailsResult = mockk<ProductDetailsResult>()
@@ -134,85 +136,91 @@ class BillingPaymentRepositoryTest {
}
@Test
- fun testPurchaseBillingProductStartPurchaseNoProductsFoundError() = runTest {
- // Arrange
- val mockProductId = ProductId("MOCK")
- val mockProductDetailsResult = mockk<ProductDetailsResult>()
- every { mockProductDetailsResult.billingResult.responseCode } returns BillingResponseCode.OK
- every { mockProductDetailsResult.productDetailsList } returns emptyList()
- coEvery { mockBillingRepository.queryProducts(listOf(mockProductId.value)) } returns
- mockProductDetailsResult
+ fun `purchaseProduct should return NoProductFound when billingRepository does not find any products`() =
+ runTest {
+ // Arrange
+ val mockProductId = ProductId("MOCK")
+ val mockProductDetailsResult = mockk<ProductDetailsResult>()
+ every { mockProductDetailsResult.billingResult.responseCode } returns
+ BillingResponseCode.OK
+ every { mockProductDetailsResult.productDetailsList } returns emptyList()
+ coEvery { mockBillingRepository.queryProducts(listOf(mockProductId.value)) } returns
+ mockProductDetailsResult
- // Act, Assert
- paymentRepository.purchaseProduct(mockProductId, mockk()).test {
- assertIs<PurchaseResult.FetchingProducts>(awaitItem())
- val result = awaitItem()
- assertIs<PurchaseResult.Error.NoProductFound>(result)
- awaitComplete()
+ // Act, Assert
+ paymentRepository.purchaseProduct(mockProductId, mockk()).test {
+ assertIs<PurchaseResult.FetchingProducts>(awaitItem())
+ val result = awaitItem()
+ assertIs<PurchaseResult.Error.NoProductFound>(result)
+ awaitComplete()
+ }
}
- }
@Test
- fun testPurchaseBillingProductStartPurchaseTransactionIdError() = runTest {
- // Arrange
- val mockProductId = ProductId("MOCK")
- val mockProductDetailsResult = mockk<ProductDetailsResult>()
- val mockProductDetails: ProductDetails = mockk()
- every { mockProductDetails.productId } returns mockProductId.value
- every { mockProductDetailsResult.billingResult.responseCode } returns BillingResponseCode.OK
- every { mockProductDetailsResult.productDetailsList } returns listOf(mockProductDetails)
- coEvery { mockBillingRepository.queryProducts(listOf(mockProductId.value)) } returns
- mockProductDetailsResult
- coEvery { mockPlayPurchaseRepository.initializePlayPurchase() } returns
- PlayPurchaseInitResult.Error(PlayPurchaseInitError.OtherError)
+ fun `purchaseProduct should return TransactionIdError on PlayPurchaseInitError from PlayPurchaseRepository`() =
+ runTest {
+ // Arrange
+ val mockProductId = ProductId("MOCK")
+ val mockProductDetailsResult = mockk<ProductDetailsResult>()
+ val mockProductDetails: ProductDetails = mockk()
+ every { mockProductDetails.productId } returns mockProductId.value
+ every { mockProductDetailsResult.billingResult.responseCode } returns
+ BillingResponseCode.OK
+ every { mockProductDetailsResult.productDetailsList } returns listOf(mockProductDetails)
+ coEvery { mockBillingRepository.queryProducts(listOf(mockProductId.value)) } returns
+ mockProductDetailsResult
+ coEvery { mockPlayPurchaseRepository.initializePlayPurchase() } returns
+ PlayPurchaseInitResult.Error(PlayPurchaseInitError.OtherError)
- // Act, Assert
- paymentRepository.purchaseProduct(mockProductId, mockk()).test {
- assertIs<PurchaseResult.FetchingProducts>(awaitItem())
- assertIs<PurchaseResult.FetchingObfuscationId>(awaitItem())
- val result = awaitItem()
- assertIs<PurchaseResult.Error.TransactionIdError>(result)
- awaitComplete()
+ // Act, Assert
+ paymentRepository.purchaseProduct(mockProductId, mockk()).test {
+ assertIs<PurchaseResult.FetchingProducts>(awaitItem())
+ assertIs<PurchaseResult.FetchingObfuscationId>(awaitItem())
+ val result = awaitItem()
+ assertIs<PurchaseResult.Error.TransactionIdError>(result)
+ awaitComplete()
+ }
}
- }
@Test
- fun testPurchaseBillingProductStartPurchaseFlowBillingError() = runTest {
- // Arrange
- val mockProductId = ProductId("MOCK")
- val mockProductDetailsResult = mockk<ProductDetailsResult>()
- val mockProductDetails: ProductDetails = mockk()
- every { mockProductDetails.productId } returns mockProductId.value
- every { mockProductDetailsResult.billingResult.responseCode } returns BillingResponseCode.OK
- every { mockProductDetailsResult.productDetailsList } returns listOf(mockProductDetails)
- coEvery { mockBillingRepository.queryProducts(listOf(mockProductId.value)) } returns
- mockProductDetailsResult
- val mockBillingResult: BillingResult = mockk()
- every { mockBillingResult.responseCode } returns BillingResponseCode.BILLING_UNAVAILABLE
- every { mockBillingResult.debugMessage } returns "Mock error"
- coEvery {
- mockBillingRepository.startPurchaseFlow(
- productDetails = any(),
- obfuscatedId = any(),
- activityProvider = any()
- )
- } returns mockBillingResult
- coEvery { mockPlayPurchaseRepository.initializePlayPurchase() } returns
- PlayPurchaseInitResult.Ok("MOCK")
+ fun `purchaseProduct should return BillingError on billing unavailable from startPurchaseFlow`() =
+ runTest {
+ // Arrange
+ val mockProductId = ProductId("MOCK")
+ val mockProductDetailsResult = mockk<ProductDetailsResult>()
+ val mockProductDetails: ProductDetails = mockk()
+ every { mockProductDetails.productId } returns mockProductId.value
+ every { mockProductDetailsResult.billingResult.responseCode } returns
+ BillingResponseCode.OK
+ every { mockProductDetailsResult.productDetailsList } returns listOf(mockProductDetails)
+ coEvery { mockBillingRepository.queryProducts(listOf(mockProductId.value)) } returns
+ mockProductDetailsResult
+ val mockBillingResult: BillingResult = mockk()
+ every { mockBillingResult.responseCode } returns BillingResponseCode.BILLING_UNAVAILABLE
+ every { mockBillingResult.debugMessage } returns "Mock error"
+ coEvery {
+ mockBillingRepository.startPurchaseFlow(
+ productDetails = any(),
+ obfuscatedId = any(),
+ activityProvider = any()
+ )
+ } returns mockBillingResult
+ coEvery { mockPlayPurchaseRepository.initializePlayPurchase() } returns
+ PlayPurchaseInitResult.Ok("MOCK")
- // Act, Assert
- paymentRepository.purchaseProduct(mockProductId, mockk()).test {
- // Purchase started
- assertIs<PurchaseResult.FetchingProducts>(awaitItem())
- assertIs<PurchaseResult.FetchingObfuscationId>(awaitItem())
- val result = awaitItem()
- assertIs<PurchaseResult.Error.BillingError>(result)
- awaitComplete()
+ // Act, Assert
+ paymentRepository.purchaseProduct(mockProductId, mockk()).test {
+ // Purchase started
+ assertIs<PurchaseResult.FetchingProducts>(awaitItem())
+ assertIs<PurchaseResult.FetchingObfuscationId>(awaitItem())
+ val result = awaitItem()
+ assertIs<PurchaseResult.Error.BillingError>(result)
+ awaitComplete()
+ }
}
- }
@Test
- fun testPurchaseBillingProductPurchaseCanceled() = runTest {
+ fun `cancel during purchaseProduct should return in cancelled event`() = runTest {
// Arrange
val mockProductId = ProductId("MOCK")
val mockProductDetailsResult = mockk<ProductDetailsResult>()
@@ -248,50 +256,52 @@ class BillingPaymentRepositoryTest {
}
@Test
- fun testPurchaseBillingProductVerificationError() = runTest {
- // Arrange
- val mockProductId = ProductId("MOCK")
- val mockProductDetailsResult = mockk<ProductDetailsResult>()
- val mockProductDetails: ProductDetails = mockk()
- every { mockProductDetails.productId } returns mockProductId.value
- every { mockProductDetailsResult.billingResult.responseCode } returns BillingResponseCode.OK
- every { mockProductDetailsResult.productDetailsList } returns listOf(mockProductDetails)
- coEvery { mockBillingRepository.queryProducts(listOf(mockProductId.value)) } returns
- mockProductDetailsResult
- val mockPurchaseToken = "TOKEN"
- val mockBillingPurchase: Purchase = mockk()
- val mockBillingResult: BillingResult = mockk()
- every { mockBillingPurchase.purchaseState } returns Purchase.PurchaseState.PURCHASED
- every { mockBillingResult.responseCode } returns BillingResponseCode.OK
- every { mockBillingPurchase.products } returns listOf(mockProductId.value)
- every { mockBillingPurchase.purchaseToken } returns mockPurchaseToken
- coEvery {
- mockBillingRepository.startPurchaseFlow(
- productDetails = any(),
- obfuscatedId = any(),
- activityProvider = any()
- )
- } returns mockBillingResult
- coEvery { mockPlayPurchaseRepository.initializePlayPurchase() } returns
- PlayPurchaseInitResult.Ok("MOCK-ID")
- coEvery { mockPlayPurchaseRepository.verifyPlayPurchase(any()) } returns
- PlayPurchaseVerifyResult.Error(PlayPurchaseVerifyError.OtherError)
+ fun `purchaseProduct should emit VerificationError on verify error from playPurchase`() =
+ runTest {
+ // Arrange
+ val mockProductId = ProductId("MOCK")
+ val mockProductDetailsResult = mockk<ProductDetailsResult>()
+ val mockProductDetails: ProductDetails = mockk()
+ every { mockProductDetails.productId } returns mockProductId.value
+ every { mockProductDetailsResult.billingResult.responseCode } returns
+ BillingResponseCode.OK
+ every { mockProductDetailsResult.productDetailsList } returns listOf(mockProductDetails)
+ coEvery { mockBillingRepository.queryProducts(listOf(mockProductId.value)) } returns
+ mockProductDetailsResult
+ val mockPurchaseToken = "TOKEN"
+ val mockBillingPurchase: Purchase = mockk()
+ val mockBillingResult: BillingResult = mockk()
+ every { mockBillingPurchase.purchaseState } returns Purchase.PurchaseState.PURCHASED
+ every { mockBillingResult.responseCode } returns BillingResponseCode.OK
+ every { mockBillingPurchase.products } returns listOf(mockProductId.value)
+ every { mockBillingPurchase.purchaseToken } returns mockPurchaseToken
+ coEvery {
+ mockBillingRepository.startPurchaseFlow(
+ productDetails = any(),
+ obfuscatedId = any(),
+ activityProvider = any()
+ )
+ } returns mockBillingResult
+ coEvery { mockPlayPurchaseRepository.initializePlayPurchase() } returns
+ PlayPurchaseInitResult.Ok("MOCK-ID")
+ coEvery { mockPlayPurchaseRepository.verifyPlayPurchase(any()) } returns
+ PlayPurchaseVerifyResult.Error(PlayPurchaseVerifyError.OtherError)
- // Act, Assert
- paymentRepository.purchaseProduct(mockProductId, mockk()).test {
- assertIs<PurchaseResult.FetchingProducts>(awaitItem())
- assertIs<PurchaseResult.FetchingObfuscationId>(awaitItem())
- assertIs<PurchaseResult.BillingFlowStarted>(awaitItem())
- purchaseEventFlow.tryEmit(PurchaseEvent.Completed(listOf(mockBillingPurchase)))
- assertIs<PurchaseResult.VerificationStarted>(awaitItem())
- val result = awaitItem()
- assertIs<PurchaseResult.Error.VerificationError>(result)
- awaitComplete()
+ // Act, Assert
+ paymentRepository.purchaseProduct(mockProductId, mockk()).test {
+ assertIs<PurchaseResult.FetchingProducts>(awaitItem())
+ assertIs<PurchaseResult.FetchingObfuscationId>(awaitItem())
+ assertIs<PurchaseResult.BillingFlowStarted>(awaitItem())
+ purchaseEventFlow.tryEmit(PurchaseEvent.Completed(listOf(mockBillingPurchase)))
+ assertIs<PurchaseResult.VerificationStarted>(awaitItem())
+ val result = awaitItem()
+ assertIs<PurchaseResult.Error.VerificationError>(result)
+ awaitComplete()
+ }
}
- }
@Test
- fun testPurchaseBillingProductPurchaseCompleted() = runTest {
+ fun `purchaseProduct success should emit all events leading up to success`() = runTest {
// Arrange
val mockProductId = ProductId("MOCK")
val mockProductDetailsResult = mockk<ProductDetailsResult>()
@@ -334,41 +344,43 @@ class BillingPaymentRepositoryTest {
}
@Test
- fun testPurchaseBillingProductPurchasePending() = runTest {
- // Arrange
- val mockProductId = ProductId("MOCK")
- val mockProductDetailsResult = mockk<ProductDetailsResult>()
- val mockProductDetails: ProductDetails = mockk()
- every { mockProductDetails.productId } returns mockProductId.value
- every { mockProductDetailsResult.billingResult.responseCode } returns BillingResponseCode.OK
- every { mockProductDetailsResult.productDetailsList } returns listOf(mockProductDetails)
- coEvery { mockBillingRepository.queryProducts(listOf(mockProductId.value)) } returns
- mockProductDetailsResult
- val mockBillingPurchase: Purchase = mockk()
- val mockBillingResult: BillingResult = mockk()
- every { mockBillingPurchase.purchaseState } returns Purchase.PurchaseState.PENDING
- every { mockBillingResult.responseCode } returns BillingResponseCode.OK
- coEvery {
- mockBillingRepository.startPurchaseFlow(
- productDetails = any(),
- obfuscatedId = any(),
- activityProvider = any()
- )
- } returns mockBillingResult
- coEvery { mockPlayPurchaseRepository.initializePlayPurchase() } returns
- PlayPurchaseInitResult.Ok("MOCK")
+ fun `purchaseProduct where purchase gets stuck in pending should complete with pending`() =
+ runTest {
+ // Arrange
+ val mockProductId = ProductId("MOCK")
+ val mockProductDetailsResult = mockk<ProductDetailsResult>()
+ val mockProductDetails: ProductDetails = mockk()
+ every { mockProductDetails.productId } returns mockProductId.value
+ every { mockProductDetailsResult.billingResult.responseCode } returns
+ BillingResponseCode.OK
+ every { mockProductDetailsResult.productDetailsList } returns listOf(mockProductDetails)
+ coEvery { mockBillingRepository.queryProducts(listOf(mockProductId.value)) } returns
+ mockProductDetailsResult
+ val mockBillingPurchase: Purchase = mockk()
+ val mockBillingResult: BillingResult = mockk()
+ every { mockBillingPurchase.purchaseState } returns Purchase.PurchaseState.PENDING
+ every { mockBillingResult.responseCode } returns BillingResponseCode.OK
+ coEvery {
+ mockBillingRepository.startPurchaseFlow(
+ productDetails = any(),
+ obfuscatedId = any(),
+ activityProvider = any()
+ )
+ } returns mockBillingResult
+ coEvery { mockPlayPurchaseRepository.initializePlayPurchase() } returns
+ PlayPurchaseInitResult.Ok("MOCK")
- // Act, Assert
- paymentRepository.purchaseProduct(mockProductId, mockk()).test {
- assertIs<PurchaseResult.FetchingProducts>(awaitItem())
- assertIs<PurchaseResult.FetchingObfuscationId>(awaitItem())
- assertIs<PurchaseResult.BillingFlowStarted>(awaitItem())
- purchaseEventFlow.tryEmit(PurchaseEvent.Completed(listOf(mockBillingPurchase)))
- val result = awaitItem()
- assertIs<PurchaseResult.Completed.Pending>(result)
- awaitComplete()
+ // Act, Assert
+ paymentRepository.purchaseProduct(mockProductId, mockk()).test {
+ assertIs<PurchaseResult.FetchingProducts>(awaitItem())
+ assertIs<PurchaseResult.FetchingObfuscationId>(awaitItem())
+ assertIs<PurchaseResult.BillingFlowStarted>(awaitItem())
+ purchaseEventFlow.tryEmit(PurchaseEvent.Completed(listOf(mockBillingPurchase)))
+ val result = awaitItem()
+ assertIs<PurchaseResult.Completed.Pending>(result)
+ awaitComplete()
+ }
}
- }
companion object {
private const val PRODUCT_DETAILS_TO_PAYMENT_PRODUCT_EXT =