Skip to content

Commit

Permalink
Paywalls: PaywallViewModel tests (#1357)
Browse files Browse the repository at this point in the history
There's more things we could test, but this is a start.
  • Loading branch information
NachoSoto authored and tonidero committed Oct 31, 2023
1 parent 4bd3b54 commit 63677bc
Show file tree
Hide file tree
Showing 6 changed files with 341 additions and 20 deletions.
3 changes: 2 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ androidx-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref
amazon-appstore-sdk = { module = "com.amazon.device:amazon-appstore-sdk", version.ref = "amazon" }

androidx-test-core = { module = "androidx.test:core-ktx", version.ref = "testLibraries" }
androidx-core-testing = { module = "androidx.arch.core:core-testing", version = "2.0.0" }
androidx-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso" }
androidx-test-junit = { module = "androidx.test.ext:junit-ktx", version.ref = "testJUnit" }
androidx-test-runner = { module = "androidx.test:runner", version.ref = "testLibraries" }
Expand Down Expand Up @@ -132,4 +133,4 @@ navigation-compose = "androidx.navigation:navigation-compose:2.5.3"
activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activity-compose" }

[bundles]
test = ["androidx-test-core", "androidx-test-runner", "androidx-test-rules", "androidx-test-junit", "robolectric", "mockk", "assertJ"]
test = ["androidx-test-core", "androidx-core-testing", "androidx-test-runner", "androidx-test-rules", "androidx-test-junit", "robolectric", "mockk", "assertJ"]
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,18 @@ data class PurchaseParams(val builder: Builder) {
@get:JvmSynthetic internal val activity: Activity,
@get:JvmSynthetic internal val purchasingData: PurchasingData,
@get:JvmSynthetic internal val presentedOfferingIdentifier: String? = null,
@get:JvmSynthetic internal val product: StoreProduct?,
) {
constructor(activity: Activity, packageToPurchase: Package) :
this(
activity,
packageToPurchase.product.purchasingData,
packageToPurchase.offering,
) {
ensureNoTestProduct(packageToPurchase.product)
}
packageToPurchase.product,
)

constructor(activity: Activity, storeProduct: StoreProduct) :
this(activity, storeProduct.purchasingData, storeProduct.presentedOfferingIdentifier) {
ensureNoTestProduct(storeProduct)
}
this(activity, storeProduct.purchasingData, storeProduct.presentedOfferingIdentifier, storeProduct)

private fun ensureNoTestProduct(storeProduct: StoreProduct) {
if (storeProduct is TestStoreProduct) {
Expand All @@ -73,7 +71,12 @@ data class PurchaseParams(val builder: Builder) {
}

constructor(activity: Activity, subscriptionOption: SubscriptionOption) :
this(activity, subscriptionOption.purchasingData, subscriptionOption.presentedOfferingIdentifier)
this(
activity,
subscriptionOption.purchasingData,
subscriptionOption.presentedOfferingIdentifier,
product = null,
)

@set:JvmSynthetic
@get:JvmSynthetic
Expand Down Expand Up @@ -136,6 +139,10 @@ data class PurchaseParams(val builder: Builder) {
}

open fun build(): PurchaseParams {
product?.let {
ensureNoTestProduct(it)
}

return PurchaseParams(this)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,7 @@ import com.revenuecat.purchases.CustomerInfo
import com.revenuecat.purchases.Offering
import com.revenuecat.purchases.Package
import com.revenuecat.purchases.PurchaseParams
import com.revenuecat.purchases.Purchases
import com.revenuecat.purchases.PurchasesException
import com.revenuecat.purchases.awaitCustomerInfo
import com.revenuecat.purchases.awaitOfferings
import com.revenuecat.purchases.awaitPurchase
import com.revenuecat.purchases.awaitRestore
import com.revenuecat.purchases.ui.revenuecatui.PaywallListener
import com.revenuecat.purchases.ui.revenuecatui.PaywallMode
import com.revenuecat.purchases.ui.revenuecatui.PaywallOptions
Expand Down Expand Up @@ -60,11 +55,11 @@ internal interface PaywallViewModel {
@Suppress("TooManyFunctions")
internal class PaywallViewModelImpl(
applicationContext: ApplicationContext,
private val purchases: PurchasesType = PurchasesImpl(),
private val options: PaywallOptions,
colorScheme: ColorScheme,
preview: Boolean = false,
) : ViewModel(), PaywallViewModel {

private val variableDataProvider = VariableDataProvider(applicationContext, preview)

override val state: StateFlow<PaywallState>
Expand Down Expand Up @@ -137,7 +132,7 @@ internal class PaywallViewModelImpl(
viewModelScope.launch {
try {
listener?.onRestoreStarted()
val customerInfo = Purchases.sharedInstance.awaitRestore()
val customerInfo = purchases.awaitRestore()
Logger.i("Restore purchases successful: $customerInfo")
listener?.onRestoreCompleted(customerInfo)
} catch (e: PurchasesException) {
Expand All @@ -160,8 +155,8 @@ internal class PaywallViewModelImpl(
viewModelScope.launch {
try {
listener?.onPurchaseStarted(packageToPurchase)
val purchaseResult = Purchases.sharedInstance.awaitPurchase(
PurchaseParams.Builder(activity, packageToPurchase).build(),
val purchaseResult = purchases.awaitPurchase(
PurchaseParams.Builder(activity, packageToPurchase),
)
listener?.onPurchaseCompleted(purchaseResult.customerInfo, purchaseResult.storeTransaction)
} catch (e: PurchasesException) {
Expand All @@ -177,7 +172,7 @@ internal class PaywallViewModelImpl(
try {
var currentOffering = options.offeringSelection.offering
if (currentOffering == null) {
val offerings = Purchases.sharedInstance.awaitOfferings()
val offerings = purchases.awaitOfferings()
currentOffering = options.offeringSelection.offeringIdentifier?.let { offerings[it] }
?: offerings.current
}
Expand All @@ -187,7 +182,7 @@ internal class PaywallViewModelImpl(
} else {
_state.value = calculateState(
currentOffering,
Purchases.sharedInstance.awaitCustomerInfo(),
purchases.awaitCustomerInfo(),
_colorScheme.value,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ internal class PaywallViewModelFactory(
private val colorScheme: ColorScheme,
private val preview: Boolean = false,
) : ViewModelProvider.NewInstanceFactory() {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return PaywallViewModelImpl(applicationContext, options, colorScheme, preview) as T
return PaywallViewModelImpl(
applicationContext = applicationContext,
options = options,
colorScheme = colorScheme,
preview = preview,
) as T
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.revenuecat.purchases.ui.revenuecatui.data

import com.revenuecat.purchases.CacheFetchPolicy
import com.revenuecat.purchases.CustomerInfo
import com.revenuecat.purchases.Offerings
import com.revenuecat.purchases.PurchaseParams
import com.revenuecat.purchases.PurchaseResult
import com.revenuecat.purchases.Purchases
import com.revenuecat.purchases.awaitCustomerInfo
import com.revenuecat.purchases.awaitOfferings
import com.revenuecat.purchases.awaitPurchase
import com.revenuecat.purchases.awaitRestore

/**
* Abstraction over [Purchases] that can be mocked.
*/
internal interface PurchasesType {
suspend fun awaitPurchase(purchaseParams: PurchaseParams.Builder): PurchaseResult

suspend fun awaitRestore(): CustomerInfo

suspend fun awaitOfferings(): Offerings

suspend fun awaitCustomerInfo(
fetchPolicy: CacheFetchPolicy = CacheFetchPolicy.default(),
): CustomerInfo
}

internal class PurchasesImpl(private val purchases: Purchases = Purchases.sharedInstance) : PurchasesType {
override suspend fun awaitPurchase(purchaseParams: PurchaseParams.Builder): PurchaseResult {
return purchases.awaitPurchase(purchaseParams.build())
}

override suspend fun awaitRestore(): CustomerInfo {
return purchases.awaitRestore()
}

override suspend fun awaitOfferings(): Offerings {
return purchases.awaitOfferings()
}

override suspend fun awaitCustomerInfo(fetchPolicy: CacheFetchPolicy): CustomerInfo {
return purchases.awaitCustomerInfo(fetchPolicy)
}
}
Loading

0 comments on commit 63677bc

Please sign in to comment.