Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paywalls: Add support for sub_period variable #1264

Merged
merged 3 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.revenuecat.purchases.models.SubscriptionOption
import com.revenuecat.purchases.models.SubscriptionOptions
import com.revenuecat.purchases.paywalls.PaywallColor
import com.revenuecat.purchases.paywalls.PaywallData
import com.revenuecat.purchases.ui.revenuecatui.R
import com.revenuecat.purchases.ui.revenuecatui.data.processed.TemplateConfiguration
import com.revenuecat.purchases.ui.revenuecatui.data.processed.VariableDataProvider
import com.revenuecat.purchases.ui.revenuecatui.helpers.ApplicationContext
Expand Down Expand Up @@ -118,6 +119,22 @@ internal class MockApplicationContext : ApplicationContext {
override fun getApplicationName(): String {
return "Mock Paywall"
}

// This is hardcoding the english version of the strings for now. We can't access the actual resources since
// we don't have access to a real context in some cases here.
override fun getString(resId: Int): String {
return when (resId) {
R.string.restore_purchases -> "Restore purchases"
R.string.annual -> "Annual"
R.string.semester -> "6 month"
R.string.quarter -> "3 month"
R.string.bimonthly -> "2 month"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied the strings from iOS. Though it felt a bit weird to not make this plural

R.string.monthly -> "Monthly"
R.string.weekly -> "Weekly"
R.string.lifetime -> "Lifetime"
else -> error("Unknown string resource $resId")
}
}
}

internal class MockViewModel(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.revenuecat.purchases.ui.revenuecatui.data.processed

import com.revenuecat.purchases.Package
import com.revenuecat.purchases.PackageType
import com.revenuecat.purchases.ui.revenuecatui.R
import com.revenuecat.purchases.ui.revenuecatui.helpers.ApplicationContext
import java.util.Locale

Expand Down Expand Up @@ -28,7 +30,17 @@ internal class VariableDataProvider(
}

fun periodName(rcPackage: Package): String {
return "PERIOD_NAME"
val stringId = when (rcPackage.packageType) {
PackageType.LIFETIME -> R.string.lifetime
PackageType.ANNUAL -> R.string.annual
PackageType.SIX_MONTH -> R.string.semester
PackageType.THREE_MONTH -> R.string.quarter
PackageType.TWO_MONTH -> R.string.bimonthly
PackageType.MONTHLY -> R.string.monthly
PackageType.WEEKLY -> R.string.weekly
PackageType.UNKNOWN, PackageType.CUSTOM -> null
}
return stringId?.let { applicationContext.getString(it) } ?: ""
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm defaulting to an empty string, which I think is the same we do in iOS.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻

}

fun subscriptionDuration(rcPackage: Package): String? {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
package com.revenuecat.purchases.ui.revenuecatui.helpers

import android.content.Context
import androidx.annotation.StringRes

/**
* Abstraction around [Context]
*/
internal interface ApplicationContext {
fun getApplicationName(): String
fun getString(@StringRes resId: Int): String
}

internal class AndroidApplicationContext(private val applicationContext: Context) : ApplicationContext {
override fun getApplicationName(): String {
return applicationContext.applicationInfo.loadLabel(applicationContext.packageManager).toString()
}

override fun getString(@StringRes resId: Int): String {
return applicationContext.resources.getString(resId)
}
}

internal fun Context.toAndroidContext(): ApplicationContext {
Expand Down
7 changes: 7 additions & 0 deletions ui/revenuecatui/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="restore_purchases">Restore purchases</string>
<string name="annual">Annual</string>
<string name="semester">6 month</string>
<string name="quarter">3 month</string>
<string name="bimonthly">2 month</string>
<string name="monthly">Monthly</string>
<string name="weekly">Weekly</string>
<string name="lifetime">Lifetime</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package com.revenuecat.purchases.ui.revenuecatui.data.processed
import android.net.Uri
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.revenuecat.purchases.Package
import com.revenuecat.purchases.PackageType
import com.revenuecat.purchases.ui.revenuecatui.PaywallViewMode
import com.revenuecat.purchases.ui.revenuecatui.data.MockApplicationContext
import com.revenuecat.purchases.ui.revenuecatui.data.TestData
import com.revenuecat.purchases.ui.revenuecatui.helpers.ApplicationContext
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Test
Expand All @@ -16,21 +17,14 @@ import java.util.Locale
internal class TemplateConfigurationFactoryTest {

private val paywallViewMode = PaywallViewMode.FULL_SCREEN
private val testAppName = "testAppName"

private lateinit var variableDataProvider: VariableDataProvider

private lateinit var template2Configuration: TemplateConfiguration

@Before
fun setUp() {
variableDataProvider = VariableDataProvider(
applicationContext = object : ApplicationContext {
override fun getApplicationName(): String {
return testAppName
}
}
)
variableDataProvider = VariableDataProvider(MockApplicationContext())
template2Configuration = TemplateConfigurationFactory.create(
variableDataProvider,
paywallViewMode,
Expand Down Expand Up @@ -87,14 +81,20 @@ internal class TemplateConfigurationFactoryTest {

private fun getPackageInfo(rcPackage: Package): TemplateConfiguration.PackageInfo {
val localizedConfiguration = TestData.template2.configForLocale(Locale.US)!!
val periodName = when(rcPackage.packageType) {
PackageType.ANNUAL -> "Annual"
PackageType.MONTHLY -> "Monthly"
PackageType.WEEKLY -> "Weekly"
else -> error("Unknown package type ${rcPackage.packageType}")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't like copying this here... But I thought it was better to kind of duplicate this logic than use the real code during the tests.

}
val processedLocalization = ProcessedLocalizedConfiguration(
title = localizedConfiguration.title,
subtitle = localizedConfiguration.subtitle,
callToAction = "Subscribe for PRICE_PER_PERIOD",
callToActionWithIntroOffer = null,
offerDetails = "PRICE_AND_PER_MONTH",
offerDetailsWithIntroOffer = "PRICE_AND_PER_MONTH after INT_OFFER_DURATION trial",
offerName = "PERIOD_NAME",
offerName = periodName,
features = emptyList(),
)
return TemplateConfiguration.PackageInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ package com.revenuecat.purchases.ui.revenuecatui.data.processed

import androidx.test.ext.junit.runners.AndroidJUnit4
import com.revenuecat.purchases.Package
import com.revenuecat.purchases.models.Price
import com.revenuecat.purchases.models.StoreProduct
import com.revenuecat.purchases.PackageType
import com.revenuecat.purchases.ui.revenuecatui.data.MockApplicationContext
import com.revenuecat.purchases.ui.revenuecatui.data.TestData
import com.revenuecat.purchases.ui.revenuecatui.helpers.ApplicationContext
import io.mockk.every
import io.mockk.mockk
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Test
Expand All @@ -26,11 +24,7 @@ class VariableProcessorTest {

@Before
fun setUp() {
applicationContext = object : ApplicationContext {
override fun getApplicationName(): String {
return "test app name"
}
}
applicationContext = MockApplicationContext()
variableDataProvider = VariableDataProvider(applicationContext)
rcPackage = TestData.Packages.annual
}
Expand All @@ -50,14 +44,14 @@ class VariableProcessorTest {
@Test
fun `process variables returns processed text with single variable`() {
val originalText = "text with {{ app_name }} one variable"
val expectedText = "text with test app name one variable"
val expectedText = "text with Mock Paywall one variable"
expectVariablesResult(originalText, expectedText)
}

@Test
fun `process variables returns processed text with multiple variable`() {
val originalText = "text with {{ app_name }} and {{ sub_price_per_month }} multiple variables"
val expectedText = "text with test app name and $5.67 multiple variables"
val expectedText = "text with Mock Paywall and $5.67 multiple variables"
expectVariablesResult(originalText, expectedText)
}

Expand All @@ -77,7 +71,7 @@ class VariableProcessorTest {

@Test
fun `process variables processes app_name`() {
expectVariablesResult("{{ app_name }}", "test app name")
expectVariablesResult("{{ app_name }}", "Mock Paywall")
}

@Test
Expand All @@ -103,8 +97,20 @@ class VariableProcessorTest {
}

@Test
fun `process variables processes sub_period`() {
expectVariablesResult("{{ sub_period }}", "PERIOD_NAME")
fun `process variables processes sub_period annual`() {
expectVariablesResult("{{ sub_period }}", "Annual")
}

@Test
fun `process variables processes sub_period monthly`() {
rcPackage = TestData.Packages.monthly
expectVariablesResult("{{ sub_period }}", "Monthly")
}

@Test
fun `process variables processes sub_period custom period`() {
rcPackage = TestData.Packages.annual.copy(packageType = PackageType.CUSTOM)
expectVariablesResult("{{ sub_period }}", "")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just want to confirm this is what we expect @NachoSoto

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah 👍🏻 I don't have a test for this in iOS but this is fine.
The idea is to have validations in the frontend / backend to prevent users from using these with custom pacakges.

}

@Test
Expand Down