Skip to content

Commit 5cab069

Browse files
authored
Refactor getBillingPeriodInDays to support all values (#6169)
Task/Issue URL: https://app.asana.com/1/137249556945/project/1201807753394693/task/1210432795362321?focus=true ### Description Refactor getBillingPeriodInDays() so we support all Google Play date ranges ### Steps to test this PR _Free Trial purchase_ - [x] Set a US account and make sure you are Privacy Pro eligible - [x] Go to paywall - [x] Check everything is fine and free trial is offered - [x] Purchase free trial _Unit tests_ - [x] Check Ci is green ✅ ### No UI changes
1 parent caf2e7b commit 5cab069

File tree

2 files changed

+78
-6
lines changed

2 files changed

+78
-6
lines changed

subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/SubscriptionsManager.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ import dagger.SingleInstanceIn
8181
import java.io.IOException
8282
import java.time.Duration
8383
import java.time.Instant
84+
import java.time.Period
85+
import java.time.format.DateTimeParseException
8486
import javax.inject.Inject
8587
import kotlin.time.Duration.Companion.milliseconds
8688
import kotlinx.coroutines.CoroutineScope
@@ -95,6 +97,7 @@ import kotlinx.coroutines.flow.onSubscription
9597
import kotlinx.coroutines.launch
9698
import kotlinx.coroutines.withContext
9799
import logcat.LogPriority.ERROR
100+
import logcat.asLog
98101
import logcat.logcat
99102
import retrofit2.HttpException
100103

@@ -1105,13 +1108,15 @@ data class PricingPhase(
11051108
val billingPeriod: String,
11061109

11071110
) {
1108-
internal fun getBillingPeriodInDays(): Int? =
1109-
when (billingPeriod) {
1110-
"P1W" -> 7
1111-
"P1M" -> 30
1112-
"P1Y" -> 365
1113-
else -> null
1111+
internal fun getBillingPeriodInDays(): Int? {
1112+
return try {
1113+
val period = Period.parse(billingPeriod)
1114+
return period.days + period.months * 30 + period.years * 365
1115+
} catch (e: DateTimeParseException) {
1116+
logcat { "Subs: Failed to parse billing period \"$billingPeriod\": ${e.asLog()}" }
1117+
null
11141118
}
1119+
}
11151120
}
11161121

11171122
data class ValidatedTokenPair(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (c) 2025 DuckDuckGo
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.duckduckgo.subscriptions.impl.billing
18+
19+
import com.duckduckgo.subscriptions.impl.PricingPhase
20+
import junit.framework.TestCase.assertEquals
21+
import junit.framework.TestCase.assertNull
22+
import org.junit.Test
23+
24+
class PricingPhaseTest {
25+
@Test
26+
fun billingPeriodParsesDaysCorrectly() {
27+
val phase = PricingPhase(formattedPrice = "Free", billingPeriod = "P10D")
28+
assertEquals(10, phase.getBillingPeriodInDays())
29+
}
30+
31+
@Test
32+
fun billingPeriodParsesWeeksCorrectly() {
33+
val phase = PricingPhase(formattedPrice = "Free", billingPeriod = "P2W")
34+
assertEquals(14, phase.getBillingPeriodInDays())
35+
}
36+
37+
@Test
38+
fun billingPeriodParsesMonthsCorrectly() {
39+
val phase = PricingPhase(formattedPrice = "Free", billingPeriod = "P2M")
40+
assertEquals(60, phase.getBillingPeriodInDays())
41+
}
42+
43+
@Test
44+
fun billingPeriodParsesYearsCorrectly() {
45+
val phase = PricingPhase(formattedPrice = "Free", billingPeriod = "P1Y")
46+
assertEquals(365, phase.getBillingPeriodInDays())
47+
}
48+
49+
@Test
50+
fun billingPeriodParsesMixedPeriodCorrectly() {
51+
val phase = PricingPhase(formattedPrice = "Free", billingPeriod = "P1Y2M10D")
52+
val expectedDays = 1 * 365 + 2 * 30 + 10 // 365 + 60 + 10 = 435
53+
assertEquals(expectedDays, phase.getBillingPeriodInDays())
54+
}
55+
56+
@Test
57+
fun billingPeriodEmptyReturnsNull() {
58+
val phase = PricingPhase(formattedPrice = "$0", billingPeriod = "")
59+
assertNull(phase.getBillingPeriodInDays())
60+
}
61+
62+
@Test
63+
fun billingPeriodReturnsNullForInvalidFormat() {
64+
val phase = PricingPhase(formattedPrice = "Free", billingPeriod = "INVALID")
65+
assertNull(phase.getBillingPeriodInDays())
66+
}
67+
}

0 commit comments

Comments
 (0)