mirror of
https://github.com/ProtonMail/protoncore_android.git
synced 2026-05-15 09:50:41 +00:00
chore: Renamed Plan to BillingPlan, disabled old plan tests.
This commit is contained in:
+19
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Proton AG
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
package me.proton.core.auth.test
|
||||
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import me.proton.core.auth.test.robot.AddAccountRobot
|
||||
@@ -27,10 +28,12 @@ import me.proton.core.humanverification.test.robot.HvCodeRobot
|
||||
import me.proton.core.paymentiap.test.robot.GPBottomSheetSubscribeErrorRobot
|
||||
import me.proton.core.paymentiap.test.robot.GPBottomSheetSubscribeRobot
|
||||
import me.proton.core.plan.test.SubscriptionHelper
|
||||
import me.proton.core.plan.test.robot.Plan
|
||||
import me.proton.core.plan.test.BillingPlan
|
||||
import me.proton.core.plan.test.robot.SubscriptionRobot
|
||||
import me.proton.core.util.kotlin.random
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
import me.proton.test.fusion.FusionConfig
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
@@ -40,7 +43,7 @@ import kotlin.time.Duration.Companion.seconds
|
||||
* Clients tests should extend it in order to run payments tests from their repositories.
|
||||
* Should be run on payments test environment with PlayStore licensed test accounts.
|
||||
* When running on Android emulator it should support PlayStore API.
|
||||
* This test is parametrized and uses [Plan]s as parameters.
|
||||
* This test is parametrized and uses [BillingPlan]s as parameters.
|
||||
* Client plans should be created in advance and maintained in clients repository.
|
||||
*
|
||||
* Usage (below code should be added on client side):
|
||||
@@ -67,7 +70,8 @@ import kotlin.time.Duration.Companion.seconds
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
public abstract class MinimalExternalRegistrationWithSubscriptionTest(private val plan: Plan) {
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public abstract class MinimalExternalRegistrationWithSubscriptionTest(private val billingPlan: BillingPlan) {
|
||||
|
||||
public abstract fun afterSubscriptionSteps()
|
||||
|
||||
@@ -99,24 +103,31 @@ public abstract class MinimalExternalRegistrationWithSubscriptionTest(private va
|
||||
.fillAndClickNext(String.random(12))
|
||||
|
||||
SubscriptionRobot
|
||||
.selectBillingCycle(plan.billingCycle)
|
||||
.selectPlan(plan)
|
||||
.selectBillingCycle(billingPlan.billingCycle)
|
||||
.selectPlan(billingPlan)
|
||||
.openPaymentMethods()
|
||||
.selectAlwaysDeclines<GPBottomSheetSubscribeRobot>()
|
||||
.clickSubscribeButton<GPBottomSheetSubscribeErrorRobot>()
|
||||
.errorMessageIsShown()
|
||||
.clickGotIt<SubscriptionRobot>()
|
||||
.selectExpandedPlan(plan)
|
||||
.selectExpandedPlan(billingPlan)
|
||||
.openPaymentMethods()
|
||||
.selectAlwaysApproves<GPBottomSheetSubscribeRobot>()
|
||||
.clickSubscribeButton<SubscriptionRobot>()
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().uiAutomation.waitForIdle(5_000L, 60_000L)
|
||||
byObject.withPkg(InstrumentationRegistry.getInstrumentation().targetContext.packageName).waitForExists()
|
||||
|
||||
HvCodeRobot
|
||||
.apply {
|
||||
waitForWebView()
|
||||
}
|
||||
|
||||
afterSubscriptionSteps()
|
||||
SubscriptionHelper.cancelSubscription(plan)
|
||||
}
|
||||
|
||||
@After
|
||||
public fun cancelPlayStoreSubscription() {
|
||||
SubscriptionHelper.cancelSubscription(billingPlan)
|
||||
}
|
||||
}
|
||||
|
||||
+21
-19
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Proton AG
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
@@ -21,6 +21,7 @@ package me.proton.core.auth.test
|
||||
import android.provider.Settings.Global.ANIMATOR_DURATION_SCALE
|
||||
import android.provider.Settings.Global.TRANSITION_ANIMATION_SCALE
|
||||
import android.provider.Settings.Global.WINDOW_ANIMATION_SCALE
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import me.proton.core.auth.test.robot.AddAccountRobot
|
||||
@@ -28,10 +29,12 @@ import me.proton.core.auth.test.robot.signup.SignupInternal
|
||||
import me.proton.core.paymentiap.test.robot.GPBottomSheetSubscribeErrorRobot
|
||||
import me.proton.core.paymentiap.test.robot.GPBottomSheetSubscribeRobot
|
||||
import me.proton.core.plan.test.SubscriptionHelper
|
||||
import me.proton.core.plan.test.robot.Plan
|
||||
import me.proton.core.plan.test.BillingPlan
|
||||
import me.proton.core.plan.test.robot.SubscriptionRobot
|
||||
import me.proton.core.util.kotlin.random
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
import me.proton.test.fusion.FusionConfig
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
@@ -41,7 +44,7 @@ import kotlin.time.Duration.Companion.seconds
|
||||
* Clients tests should extend it in order to run payments tests from their repositories.
|
||||
* Should be run on payments test environment with PlayStore licensed test accounts.
|
||||
* When running on Android emulator it should support PlayStore API.
|
||||
* This test is parametrized and uses [Plan]s as parameters.
|
||||
* This test is parametrized and uses [BillingPlan]s as parameters.
|
||||
* Client plans should be created in advance and maintained in clients repository.
|
||||
*
|
||||
* Usage (below code should be added on client side):
|
||||
@@ -68,25 +71,16 @@ import kotlin.time.Duration.Companion.seconds
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
public abstract class MinimalInternalRegistrationWithSubscriptionTest(private val plan: Plan) {
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public abstract class MinimalInternalRegistrationWithSubscriptionTest(private val billingPlan: BillingPlan) {
|
||||
|
||||
public abstract fun afterSubscriptionSteps()
|
||||
|
||||
@Before
|
||||
public fun setUpTimeouts() {
|
||||
val animationScale: Float = 0.0F
|
||||
val transitionAnimationScale: Float = 0.0F
|
||||
val animatorDurationScale: Float = 0.0F
|
||||
InstrumentationRegistry.getInstrumentation().uiAutomation
|
||||
.executeShellCommand("settings put secure $ANIMATOR_DURATION_SCALE $animationScale")
|
||||
InstrumentationRegistry.getInstrumentation().uiAutomation
|
||||
.executeShellCommand("settings put secure $TRANSITION_ANIMATION_SCALE $transitionAnimationScale")
|
||||
InstrumentationRegistry.getInstrumentation().uiAutomation
|
||||
.executeShellCommand("settings put secure $WINDOW_ANIMATION_SCALE $animatorDurationScale")
|
||||
FusionConfig.Compose.waitTimeout.set(60.seconds)
|
||||
FusionConfig.Espresso.waitTimeout.set(60.seconds)
|
||||
FusionConfig.UiAutomator.waitTimeout.set(60.seconds)
|
||||
FusionConfig.UiAutomator.shouldSearchByObjectEachAction = false
|
||||
InstrumentationRegistry.getInstrumentation().uiAutomation
|
||||
.executeShellCommand("settings put secure autofill_service null")
|
||||
}
|
||||
@@ -112,20 +106,28 @@ public abstract class MinimalInternalRegistrationWithSubscriptionTest(private va
|
||||
.skipConfirm()
|
||||
|
||||
SubscriptionRobot
|
||||
.selectBillingCycle(plan.billingCycle)
|
||||
.selectPlan(plan)
|
||||
.selectBillingCycle(billingPlan.billingCycle)
|
||||
.selectPlan(billingPlan)
|
||||
|
||||
.openPaymentMethods()
|
||||
.selectAlwaysDeclines<GPBottomSheetSubscribeRobot>()
|
||||
.clickSubscribeButton<GPBottomSheetSubscribeErrorRobot>()
|
||||
.errorMessageIsShown()
|
||||
.clickGotIt<SubscriptionRobot>()
|
||||
.selectExpandedPlan(plan)
|
||||
|
||||
.selectExpandedPlan(billingPlan)
|
||||
.openPaymentMethods()
|
||||
.selectAlwaysApproves<GPBottomSheetSubscribeRobot>()
|
||||
.clickSubscribeButton<SubscriptionRobot>()
|
||||
|
||||
afterSubscriptionSteps()
|
||||
InstrumentationRegistry.getInstrumentation().uiAutomation.waitForIdle(5_000L, 60_000L)
|
||||
byObject.withPkg(InstrumentationRegistry.getInstrumentation().targetContext.packageName).waitForExists()
|
||||
|
||||
SubscriptionHelper.cancelSubscription(plan)
|
||||
afterSubscriptionSteps()
|
||||
}
|
||||
|
||||
@After
|
||||
public fun cancelPlayStoreSubscription() {
|
||||
SubscriptionHelper.cancelSubscription(billingPlan)
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -23,6 +23,7 @@ import androidx.test.core.app.ApplicationProvider
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import me.proton.core.domain.entity.AppStore
|
||||
import me.proton.core.payment.presentation.R
|
||||
import me.proton.core.plan.test.BillingPlan
|
||||
import me.proton.core.plan.test.robot.SubscriptionRobot
|
||||
import me.proton.core.test.android.instrumented.utils.StringUtils.stringFromResource
|
||||
import me.proton.core.test.android.robot.CoreexampleRobot
|
||||
@@ -63,7 +64,7 @@ class DynamicExistingPaymentMethodTests(
|
||||
login(userWithPaypal)
|
||||
|
||||
CoreexampleRobot().plansUpgrade()
|
||||
SubscriptionRobot.selectPlan(Plan.Dev)
|
||||
SubscriptionRobot.selectPlan(BillingPlan.Free)
|
||||
ExistingPaymentMethodsRobot().verify {
|
||||
paymentMethodDisplayed("PayPal", userWithPaypal.paypal)
|
||||
}
|
||||
@@ -74,7 +75,7 @@ class DynamicExistingPaymentMethodTests(
|
||||
login(userWithCard)
|
||||
|
||||
CoreexampleRobot().plansUpgrade()
|
||||
SubscriptionRobot.selectPlan(Plan.Dev)
|
||||
SubscriptionRobot.selectPlan(BillingPlan.Free)
|
||||
ExistingPaymentMethodsRobot().verify {
|
||||
paymentMethodDisplayed(Card.default.details(), Card.default.name)
|
||||
if (inApp) {
|
||||
@@ -93,7 +94,7 @@ class DynamicExistingPaymentMethodTests(
|
||||
login(user)
|
||||
|
||||
CoreexampleRobot().plansUpgrade()
|
||||
SubscriptionRobot.selectPlan(Plan.Dev)
|
||||
SubscriptionRobot.selectPlan(BillingPlan.Free)
|
||||
ExistingPaymentMethodsRobot().verify {
|
||||
paymentMethodDisplayed(card.details(), card.name)
|
||||
paymentMethodDisplayed("PayPal", user.paypal)
|
||||
@@ -106,7 +107,7 @@ class DynamicExistingPaymentMethodTests(
|
||||
val user = users.getUser { it.paypal.isNotEmpty() && it.cards.isNotEmpty() && !it.isPaid }
|
||||
|
||||
CoreexampleRobot().plansUpgrade()
|
||||
SubscriptionRobot.selectPlan(Plan.Dev)
|
||||
SubscriptionRobot.selectPlan(BillingPlan.Free)
|
||||
ExistingPaymentMethodsRobot().verify {
|
||||
paymentMethod(user.paypal).checkIsNotChecked()
|
||||
paymentMethod(user.cards[0].details()).checkIsChecked()
|
||||
|
||||
+3
-3
@@ -21,11 +21,11 @@ package me.proton.core.test.android.uitests.tests.medium.payments
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import me.proton.core.domain.entity.AppStore
|
||||
import me.proton.core.payment.presentation.R
|
||||
import me.proton.core.plan.test.BillingPlan
|
||||
import me.proton.core.plan.test.robot.SubscriptionRobot
|
||||
import me.proton.core.test.android.robots.payments.AddCreditCardRobot
|
||||
import me.proton.core.test.android.robot.CoreexampleRobot
|
||||
import me.proton.core.test.android.robots.payments.AddCreditCardRobot
|
||||
import me.proton.core.test.android.uitests.tests.BaseTest
|
||||
import me.proton.core.test.quark.data.Plan
|
||||
import me.proton.core.test.quark.data.User
|
||||
import org.junit.After
|
||||
import org.junit.Test
|
||||
@@ -46,7 +46,7 @@ class DynamicNewCreditCardTests : BaseTest() {
|
||||
login(userWithoutCard)
|
||||
|
||||
CoreexampleRobot().plansCurrent()
|
||||
SubscriptionRobot.selectPlan(Plan.Dev)
|
||||
SubscriptionRobot.selectPlan(BillingPlan.Free)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
-1
@@ -21,7 +21,6 @@ package me.proton.core.test.android.uitests.tests.medium.plans
|
||||
import android.content.Context
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import me.proton.core.domain.entity.AppStore
|
||||
import me.proton.core.plan.presentation.R
|
||||
import me.proton.core.plan.presentation.entity.PlanCycle
|
||||
|
||||
+1
@@ -37,6 +37,7 @@ import java.text.DateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
|
||||
@Ignore("Outdated")
|
||||
@HiltAndroidTest
|
||||
class DynamicCurrentPlanTests {
|
||||
|
||||
|
||||
+8
-9
@@ -27,12 +27,11 @@ import me.proton.core.auth.test.robot.signup.SetPasswordRobot
|
||||
import me.proton.core.domain.entity.AppStore
|
||||
import me.proton.core.humanverification.test.robot.HvCodeRobot
|
||||
import me.proton.core.paymentiap.test.robot.GoogleIAPRobot
|
||||
import me.proton.core.plan.test.BillingPlan
|
||||
import me.proton.core.plan.test.robot.SubscriptionRobot
|
||||
import me.proton.core.test.android.robots.CoreRobot
|
||||
import me.proton.core.test.android.robots.payments.AddCreditCardRobot
|
||||
import me.proton.core.test.android.uitests.tests.SmokeTest
|
||||
import me.proton.core.test.quark.data.Plan.Free
|
||||
import me.proton.core.test.quark.data.Plan.MailPlus
|
||||
import me.proton.core.test.rule.annotation.TestUserData
|
||||
import me.proton.core.test.rule.annotation.payments.TestPaymentMethods
|
||||
import me.proton.core.test.rule.annotation.payments.annotationTestData
|
||||
@@ -42,7 +41,7 @@ import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
//@Ignore("Outdated")
|
||||
@Ignore("Outdated")
|
||||
@HiltAndroidTest
|
||||
class DynamicSelectPlanTests {
|
||||
|
||||
@@ -82,7 +81,7 @@ class DynamicSelectPlanTests {
|
||||
|
||||
@Test
|
||||
fun selectFreeAndCancelHumanVerification() {
|
||||
SubscriptionRobot.selectPlan(Free)
|
||||
SubscriptionRobot.selectPlan(BillingPlan.Free)
|
||||
|
||||
HvCodeRobot
|
||||
.apply {
|
||||
@@ -95,7 +94,7 @@ class DynamicSelectPlanTests {
|
||||
|
||||
@Test
|
||||
fun selectFreeAndCancelHumanVerification2() {
|
||||
SubscriptionRobot.selectPlan(MailPlus)
|
||||
SubscriptionRobot.selectPlan(BillingPlan.Free)
|
||||
|
||||
HvCodeRobot
|
||||
.apply {
|
||||
@@ -109,7 +108,7 @@ class DynamicSelectPlanTests {
|
||||
@Test
|
||||
@SmokeTest
|
||||
fun selectPlusAndCancelPayment() {
|
||||
SubscriptionRobot.selectPlan(MailPlus)
|
||||
SubscriptionRobot.selectPlan(BillingPlan.Free)
|
||||
AddCreditCardRobot()
|
||||
.apply {
|
||||
verify<AddCreditCardRobot.Verify> {
|
||||
@@ -125,7 +124,7 @@ class DynamicSelectPlanTests {
|
||||
@SmokeTest
|
||||
@TestPaymentMethods(AppStore.GooglePlay, card = false, paypal = false, inApp = true)
|
||||
fun selectPlusAndCancelPaymentIAPOnly() {
|
||||
SubscriptionRobot.selectPlan(MailPlus)
|
||||
SubscriptionRobot.selectPlan(BillingPlan.Free)
|
||||
GoogleIAPRobot()
|
||||
.apply {
|
||||
verify<GoogleIAPRobot.Verify> {
|
||||
@@ -141,7 +140,7 @@ class DynamicSelectPlanTests {
|
||||
@SmokeTest
|
||||
@TestPaymentMethods(AppStore.GooglePlay, card = true, paypal = false, inApp = true)
|
||||
fun selectPlusAndCancelPaymentIAPAndCard() {
|
||||
SubscriptionRobot.selectPlan(MailPlus)
|
||||
SubscriptionRobot.selectPlan(BillingPlan.Free)
|
||||
AddCreditCardRobot()
|
||||
.apply {
|
||||
verify<AddCreditCardRobot.Verify> { nextPaymentProviderButtonDisplayed() }
|
||||
@@ -159,7 +158,7 @@ class DynamicSelectPlanTests {
|
||||
@SmokeTest
|
||||
@TestPaymentMethods(AppStore.GooglePlay, card = false, paypal = false, inApp = false)
|
||||
fun selectPlusNoPaymentProvidersAvailable() {
|
||||
SubscriptionRobot.selectPlan(MailPlus)
|
||||
SubscriptionRobot.selectPlan(BillingPlan.Free)
|
||||
SubscriptionRobot.verifyAtLeastOnePlanIsShown()
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -21,6 +21,7 @@ package me.proton.core.test.android.uitests.tests.medium.plans
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import me.proton.core.domain.entity.AppStore
|
||||
import me.proton.core.plan.presentation.entity.PlanCycle
|
||||
import me.proton.core.plan.test.BillingPlan
|
||||
import me.proton.core.plan.test.robot.SubscriptionRobot
|
||||
import me.proton.core.test.android.robot.CoreexampleRobot
|
||||
import me.proton.core.test.android.uitests.tests.BaseTest
|
||||
@@ -29,8 +30,10 @@ import me.proton.core.test.quark.data.Plan
|
||||
import me.proton.core.test.quark.data.User
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
@Ignore("Outdated")
|
||||
@HiltAndroidTest
|
||||
class DynamicUpgradePlanTests : BaseTest() {
|
||||
private val coreExampleRobot = CoreexampleRobot()
|
||||
@@ -55,8 +58,8 @@ class DynamicUpgradePlanTests : BaseTest() {
|
||||
|
||||
coreExampleRobot.plansUpgrade()
|
||||
SubscriptionRobot.apply {
|
||||
togglePlan(Plan.Dev)
|
||||
verifyCanGetPlan(Plan.Dev)
|
||||
togglePlan(BillingPlan.Free)
|
||||
verifyCanGetPlan(BillingPlan.Free)
|
||||
close()
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -18,7 +18,6 @@
|
||||
|
||||
package me.proton.core.test.android.uitests.tests.medium.plans
|
||||
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import me.proton.core.domain.entity.AppStore
|
||||
import me.proton.core.test.quark.data.Plan.Dev
|
||||
import me.proton.core.test.quark.data.Plan.Free
|
||||
|
||||
-1
@@ -18,7 +18,6 @@
|
||||
|
||||
package me.proton.core.test.android.uitests.tests.medium.plans
|
||||
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import me.proton.core.domain.entity.AppStore
|
||||
import me.proton.core.plan.presentation.entity.PlanCycle
|
||||
import me.proton.core.test.quark.data.Plan
|
||||
|
||||
@@ -10,4 +10,3 @@ android.enableJetifier=false
|
||||
kotlin.code.style=official
|
||||
android.nonTransitiveRClass=false
|
||||
android.nonFinalResIds=false
|
||||
android.testInstrumentationRunnerArguments.no-uninstall=true
|
||||
|
||||
+23
-4
@@ -1,15 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.paymentiap.test.robot
|
||||
|
||||
import android.widget.TextView
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.uiautomator.UiDevice
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
|
||||
/**
|
||||
* Payment method bottom sheet robot to select always declines or always approves methods.
|
||||
*/
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public class GPBottomSheetPaymentMethodsRobot {
|
||||
|
||||
public val device: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
|
||||
|
||||
public inline fun <reified T> selectAlwaysApproves(): T {
|
||||
selectCardItem(testCardAlwaysApprovesText)
|
||||
return T::class.java.getDeclaredConstructor().newInstance()
|
||||
|
||||
+23
@@ -1,10 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.paymentiap.test.robot
|
||||
|
||||
import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import me.proton.core.test.android.instrumented.FusionConfig
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
|
||||
/**
|
||||
* Google Play payment error bottom sheet robot, containing actions and validations.
|
||||
*/
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public class GPBottomSheetSubscribeErrorRobot {
|
||||
|
||||
public inline fun <reified T> clickGotIt(): T {
|
||||
|
||||
+48
-1
@@ -1,7 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.paymentiap.test.robot
|
||||
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RadioButton
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.uiautomator.By
|
||||
import androidx.test.uiautomator.UiDevice
|
||||
@@ -9,13 +29,17 @@ import androidx.test.uiautomator.UiWatcher
|
||||
import me.proton.core.test.android.instrumented.FusionConfig
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
|
||||
/**
|
||||
* Google Play bottom sheet robot, containing Subscribe button with additional actions.
|
||||
*/
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public class GPBottomSheetSubscribeRobot {
|
||||
|
||||
private val device: UiDevice =
|
||||
UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
|
||||
public fun registerPlayPointsNotNowButtonWatcher() {
|
||||
device.registerWatcher("Google play Points Not now button watcher", UiWatcher {
|
||||
device.registerWatcher(notNowButtonUiWatcherName, UiWatcher {
|
||||
val registerButton = device.findObject(By.text("Not now").clazz(Button::class.java))
|
||||
if (registerButton != null && registerButton.isEnabled) {
|
||||
println("'Google play Points Not now' button detected! Clicking it now...")
|
||||
@@ -27,6 +51,25 @@ public class GPBottomSheetSubscribeRobot {
|
||||
device.runWatchers()
|
||||
}
|
||||
|
||||
public fun registerPlayRequireAuthenticationWatcher() {
|
||||
device.registerWatcher(authRequiredScreenWatcherName, UiWatcher {
|
||||
val noThanksButton =
|
||||
device.findObject(By.text("No, thanks").clazz(RadioButton::class.java))
|
||||
if (noThanksButton != null) {
|
||||
println("'Google play authentication required screen is shown. Dealing with it.")
|
||||
noThanksButton.click()
|
||||
val okButton =
|
||||
device.findObject(By.text("OK").clazz(Button::class.java).enabled(true))
|
||||
if (okButton != null) {
|
||||
okButton.click()
|
||||
return@UiWatcher true
|
||||
}
|
||||
}
|
||||
false
|
||||
})
|
||||
device.runWatchers()
|
||||
}
|
||||
|
||||
public fun openPaymentMethods(): GPBottomSheetPaymentMethodsRobot {
|
||||
FusionConfig.uiAutomator.boost()
|
||||
byObject
|
||||
@@ -48,7 +91,11 @@ public class GPBottomSheetSubscribeRobot {
|
||||
.waitForExists()
|
||||
.click()
|
||||
|
||||
// Below UIWatchers should handle one time pop-up bottom sheets:
|
||||
// PlayStore points and require PlayStore authentication.
|
||||
registerPlayPointsNotNowButtonWatcher()
|
||||
registerPlayRequireAuthenticationWatcher()
|
||||
|
||||
return T::class.java.getDeclaredConstructor().newInstance()
|
||||
}
|
||||
}
|
||||
+23
-1
@@ -1,12 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.paymentiap.test.robot
|
||||
|
||||
import android.widget.TextView
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
|
||||
/**
|
||||
* Google Play bottom sheet containing Subscribe button with additional actions.
|
||||
*/
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public class PlayStoreAccountViewRobot {
|
||||
|
||||
public fun selectPaymentsAndSubscriptionsItem(): PlayStorePaymentsAndSubscriptionsRobot {
|
||||
Thread.sleep(3000)
|
||||
byObject.withText("Payments & subscriptions")
|
||||
.instanceOf(TextView::class.java)
|
||||
.waitForExists()
|
||||
|
||||
+20
@@ -1,8 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.paymentiap.test.robot
|
||||
|
||||
import android.widget.TextView
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public class PlayStoreCancelSubscriptionBottomSheetRobot {
|
||||
|
||||
public fun clickCancelSubscription(): PlayStoreManageSubscriptionRobot {
|
||||
|
||||
+50
@@ -1,11 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.paymentiap.test.robot
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.widget.Button
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.uiautomator.By
|
||||
import androidx.test.uiautomator.UiDevice
|
||||
import androidx.test.uiautomator.UiWatcher
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
|
||||
/**
|
||||
* Contains code to launch PlayStore app and deal with PlayStore application home screen.
|
||||
*/
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public class PlayStoreHomeRobot {
|
||||
|
||||
public fun clickOnAccountButton(): PlayStoreAccountViewRobot {
|
||||
@@ -17,10 +46,31 @@ public class PlayStoreHomeRobot {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
context.startActivity(intent)
|
||||
|
||||
registerMeetTheSearchTabWatcher()
|
||||
|
||||
byObject.withContentDescContains("Signed in as")
|
||||
.instanceOf(FrameLayout::class.java)
|
||||
.waitForExists()
|
||||
.click()
|
||||
return PlayStoreAccountViewRobot()
|
||||
}
|
||||
|
||||
private val device: UiDevice =
|
||||
UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
|
||||
public fun registerMeetTheSearchTabWatcher() {
|
||||
device.registerWatcher(playStoreMeetTheSearchTabName, UiWatcher {
|
||||
val meetTheSearchTab = device.findObject(By.text("Meet the Search tab").clazz(TextView::class.java))
|
||||
if (meetTheSearchTab != null) {
|
||||
println("Handling 'Google play Meet the Search tab' pop up.")
|
||||
val searchTab = device.findObject(By.text("Search").clazz(TextView::class.java).pkg("com.android.vending"))
|
||||
if (searchTab != null) {
|
||||
searchTab.click()
|
||||
return@UiWatcher true
|
||||
}
|
||||
}
|
||||
false
|
||||
})
|
||||
device.runWatchers()
|
||||
}
|
||||
}
|
||||
+20
@@ -1,9 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.paymentiap.test.robot
|
||||
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public class PlayStoreManageSubscriptionRobot {
|
||||
|
||||
public fun clickCancelSubscription(): PlayStorePauseSubscriptionBottomSheetRobot {
|
||||
|
||||
+20
@@ -1,8 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.paymentiap.test.robot
|
||||
|
||||
import android.widget.TextView
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public class PlayStorePauseSubscriptionBottomSheetRobot {
|
||||
|
||||
public fun clickNoThanksButton(isMonthlyBillingCycle: Boolean): PlayStoreWhatsMakingYouCancelRobot {
|
||||
|
||||
+20
@@ -1,8 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.paymentiap.test.robot
|
||||
|
||||
import android.widget.TextView
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public class PlayStorePaymentsAndSubscriptionsRobot {
|
||||
|
||||
public fun selectSubscriptionsItem(): PlayStoreSubscriptionsRobot {
|
||||
|
||||
+20
@@ -1,8 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.paymentiap.test.robot
|
||||
|
||||
import android.widget.TextView
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public class PlayStoreSubscriptionsRobot {
|
||||
|
||||
public fun clickActiveSubscriptionByText(planName: String): PlayStoreManageSubscriptionRobot {
|
||||
|
||||
+20
@@ -1,9 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.paymentiap.test.robot
|
||||
|
||||
import android.widget.RadioButton
|
||||
import android.widget.TextView
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public class PlayStoreWhatsMakingYouCancelRobot {
|
||||
|
||||
public fun clickIDontUseServiceEnoughItemAndPressContinue(): PlayStoreCancelSubscriptionBottomSheetRobot {
|
||||
|
||||
+21
-3
@@ -1,10 +1,28 @@
|
||||
package me.proton.core.paymentiap.test.robot
|
||||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import me.proton.core.paymentiap.test.R
|
||||
import me.proton.core.presentation.ui.view.ProtonButton
|
||||
package me.proton.core.paymentiap.test.robot
|
||||
|
||||
public const val playStorePkg: String = "com.android.vending"
|
||||
public const val testCardAlwaysDeclinesText: String = "Test card, always declines"
|
||||
public const val testCardAlwaysApprovesText: String = "Test card, always approves"
|
||||
public const val testCardAlwaysText: String = "Test card, always"
|
||||
public const val googlePlayManagedSubscriptionText: String = "Your subscription is managed by Google Play."
|
||||
public const val notNowButtonUiWatcherName: String = "Google play Points Not now button watcher"
|
||||
public const val authRequiredScreenWatcherName: String = "Google play Points Not now button watcher"
|
||||
public const val playStoreMeetTheSearchTabName: String = "Google play meet the search tab"
|
||||
|
||||
@@ -42,9 +42,7 @@ dependencies {
|
||||
project(Module.humanVerificationTest),
|
||||
project(Module.planPresentation),
|
||||
project(Module.paymentIapTest),
|
||||
project(Module.paymentIapData),
|
||||
project(Module.androidUtilDagger),
|
||||
// project(Module.authTest),
|
||||
project(Module.testRule),
|
||||
fusion,
|
||||
`kotlin-test`,
|
||||
|
||||
@@ -61,5 +61,4 @@ public abstract class MinimalSubscriptionTests {
|
||||
currentPlanIsDisplayed()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,31 +18,31 @@
|
||||
|
||||
package me.proton.core.plan.test
|
||||
|
||||
import androidx.test.filters.SdkSuppress
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import me.proton.core.payment.domain.PurchaseManager
|
||||
import me.proton.core.payment.domain.entity.PurchaseState
|
||||
import me.proton.core.paymentiap.data.GooglePurchaseStateHandler
|
||||
import me.proton.core.paymentiap.test.robot.GPBottomSheetSubscribeErrorRobot
|
||||
import me.proton.core.paymentiap.test.robot.GPBottomSheetSubscribeRobot
|
||||
import me.proton.core.plan.test.robot.Plan
|
||||
import me.proton.core.plan.test.robot.SubscriptionRobot
|
||||
import me.proton.core.test.rule.annotation.PrepareUser
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
import me.proton.test.fusion.FusionConfig
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import javax.inject.Inject
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@HiltAndroidTest
|
||||
public abstract class MinimalUpgradeFreeUserTest(private val plan: Plan) {
|
||||
@SdkSuppress(minSdkVersion = 33)
|
||||
public abstract class MinimalUpgradeFreeUserTest(private val billingPlan: BillingPlan) {
|
||||
|
||||
@Inject
|
||||
internal lateinit var purchaseManager: PurchaseManager
|
||||
|
||||
@Inject
|
||||
internal lateinit var giapHandler: GooglePurchaseStateHandler
|
||||
|
||||
public abstract fun startSubscription(): SubscriptionRobot
|
||||
|
||||
public abstract fun afterSubscriptionSteps()
|
||||
@@ -58,23 +58,43 @@ public abstract class MinimalUpgradeFreeUserTest(private val plan: Plan) {
|
||||
@PrepareUser(loginBefore = true)
|
||||
public fun upgradeFreeUserToPlanFailFirstPaymentAttempt(): Unit = runBlocking {
|
||||
startSubscription()
|
||||
.selectBillingCycle(plan.billingCycle)
|
||||
.selectPlan(plan)
|
||||
.selectBillingCycle(billingPlan.billingCycle)
|
||||
.selectPlan(billingPlan)
|
||||
// Error flow
|
||||
.openPaymentMethods()
|
||||
.selectAlwaysDeclines<GPBottomSheetSubscribeRobot>()
|
||||
.clickSubscribeButton<GPBottomSheetSubscribeErrorRobot>()
|
||||
.errorMessageIsShown()
|
||||
// Success flow
|
||||
.clickGotIt<SubscriptionRobot>()
|
||||
.selectExpandedPlan(plan)
|
||||
.selectExpandedPlan(billingPlan)
|
||||
.openPaymentMethods()
|
||||
.selectAlwaysApproves<GPBottomSheetSubscribeRobot>()
|
||||
.clickSubscribeButton<SubscriptionRobot>()
|
||||
|
||||
GiapHandler(giapHandler).waitForGiapSubscribed(plan)
|
||||
GiapHandler(giapHandler).waitForGiapAcknowledged(plan)
|
||||
PurchaseManagerHandler(purchaseManager).waitForPurchaseState(plan, PurchaseState.Deleted)
|
||||
PurchaseManagerHandler(purchaseManager).waitForPurchaseState(
|
||||
billingPlan,
|
||||
PurchaseState.Subscribed
|
||||
)
|
||||
PurchaseManagerHandler(purchaseManager).waitForPurchaseState(
|
||||
billingPlan,
|
||||
PurchaseState.Acknowledged
|
||||
)
|
||||
PurchaseManagerHandler(purchaseManager).waitForPurchaseState(
|
||||
billingPlan,
|
||||
PurchaseState.Deleted
|
||||
)
|
||||
|
||||
InstrumentationRegistry.getInstrumentation()
|
||||
.uiAutomation.waitForIdle(5_000L, 30_000L)
|
||||
byObject.withPkg(InstrumentationRegistry.getInstrumentation().targetContext.packageName)
|
||||
.waitForExists()
|
||||
|
||||
afterSubscriptionSteps()
|
||||
SubscriptionHelper.cancelSubscription(plan)
|
||||
}
|
||||
|
||||
@After
|
||||
public fun cancelPlayStoreSubscription() {
|
||||
SubscriptionHelper.cancelSubscription(billingPlan)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Proton AG
|
||||
* This file is part of Proton AG and ProtonCore.
|
||||
*
|
||||
* ProtonCore is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ProtonCore is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.proton.core.plan.test
|
||||
|
||||
/**
|
||||
* Represents billing plan object used in Payments tests with its billing cycle.
|
||||
*/
|
||||
|
||||
public data class BillingPlan(
|
||||
val id: String,
|
||||
val name: String,
|
||||
val price: Double,
|
||||
val billingCycle: BillingCycle
|
||||
) {
|
||||
|
||||
override fun toString(): String {
|
||||
// Show only BillingPlan name & BillingPlan cycle in parametrized test
|
||||
return "$name, ${billingCycle.value}"
|
||||
}
|
||||
|
||||
public companion object {
|
||||
// Predefined Billing Cycles
|
||||
public val Free: BillingPlan =
|
||||
BillingPlan("Free", "Free", 0.0, BillingCycle(BillingCycle.PAY_MONTHLY))
|
||||
}
|
||||
}
|
||||
|
||||
public data class BillingCycle(
|
||||
val value: String
|
||||
) {
|
||||
public companion object {
|
||||
// Predefined payment period values
|
||||
public const val PAY_ANNUALLY: String = "Pay annually"
|
||||
public const val PAY_MONTHLY: String = "Pay monthly"
|
||||
}
|
||||
}
|
||||
@@ -1,91 +1,50 @@
|
||||
package me.proton.core.plan.test
|
||||
|
||||
import android.util.Log
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import me.proton.core.payment.domain.PurchaseManager
|
||||
import me.proton.core.payment.domain.entity.Purchase
|
||||
import me.proton.core.payment.domain.entity.PurchaseState
|
||||
import me.proton.core.paymentiap.data.GooglePurchaseStateHandler
|
||||
import me.proton.core.paymentiap.data.onGiapAcknowledged
|
||||
import me.proton.core.paymentiap.data.onGiapSubscribed
|
||||
import me.proton.core.payment.domain.onPurchaseState
|
||||
import me.proton.core.paymentiap.test.robot.PlayStoreHomeRobot
|
||||
import me.proton.core.plan.test.robot.BillingCycle
|
||||
import me.proton.core.plan.test.robot.Plan
|
||||
|
||||
public class GiapHandler(private val giapHandler: GooglePurchaseStateHandler) {
|
||||
|
||||
public fun waitForGiapSubscribed(plan: Plan) {
|
||||
runBlocking {
|
||||
repeat(10) {
|
||||
val job = giapHandler.onGiapSubscribed(plan.id) {
|
||||
Log.d(
|
||||
"GIAP_TEST",
|
||||
"✅ GIAP -> Subscription subscribed: ${plan.name} - ${plan.id}"
|
||||
)
|
||||
}
|
||||
if (job.isCompleted) {
|
||||
return@repeat
|
||||
}
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun waitForGiapAcknowledged(plan: Plan) {
|
||||
runBlocking {
|
||||
repeat(10) {
|
||||
val job = giapHandler.onGiapAcknowledged(plan.id)
|
||||
{
|
||||
Log.d(
|
||||
"GIAP_TEST",
|
||||
"✅ GIAP -> Subscription acknowledged: ${plan.name} - ${plan.id}"
|
||||
)
|
||||
}
|
||||
if (job.isCompleted) {
|
||||
return@repeat
|
||||
}
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PurchaseManagerHandler(private val purchaseManager: PurchaseManager) {
|
||||
public suspend fun waitForPurchaseState(plan: Plan, state: PurchaseState): Purchase? {
|
||||
repeat(10) {
|
||||
val purchase = purchaseManager
|
||||
.observePurchase(plan.id)
|
||||
.filter { it?.purchaseState == state }
|
||||
.firstOrNull()
|
||||
if (purchase != null) {
|
||||
public fun waitForPurchaseState(
|
||||
billingPlan: BillingPlan,
|
||||
state: PurchaseState,
|
||||
timeMills: Long = 10000
|
||||
) {
|
||||
runBlocking {
|
||||
withTimeoutOrNull(timeMills) {
|
||||
purchaseManager.onPurchaseState(state, planName = billingPlan.id).first()
|
||||
Log.d(
|
||||
"GIAP_TEST",
|
||||
"✅ PurchaseManager -> Purchase deleted from database: ${plan.name} - ${plan.id}"
|
||||
"✅ PurchaseManager -> Purchase is in state '$state': " +
|
||||
"${billingPlan.name} - ${billingPlan.id}"
|
||||
)
|
||||
return purchase
|
||||
}
|
||||
delay(1000)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
public object SubscriptionHelper {
|
||||
|
||||
public fun cancelSubscription(plan: Plan) {
|
||||
public fun cancelSubscription(billingPlan: BillingPlan) {
|
||||
PlayStoreHomeRobot()
|
||||
.clickOnAccountButton()
|
||||
.selectPaymentsAndSubscriptionsItem()
|
||||
.selectSubscriptionsItem()
|
||||
.clickActiveSubscriptionByText(
|
||||
plan.name.takeIf { plan.billingCycle.value == BillingCycle.PAY_ANNUALLY }
|
||||
?: "${plan.name} 1 month"
|
||||
billingPlan.name.takeIf {
|
||||
billingPlan.billingCycle.value == BillingCycle.PAY_ANNUALLY
|
||||
}
|
||||
?: "${billingPlan.name} 1 month"
|
||||
)
|
||||
.clickCancelSubscription()
|
||||
.clickNoThanksButton(plan.billingCycle.value == BillingCycle.PAY_MONTHLY)
|
||||
.clickNoThanksButton(
|
||||
billingPlan.billingCycle.value == BillingCycle.PAY_MONTHLY
|
||||
)
|
||||
.clickIDontUseServiceEnoughItemAndPressContinue()
|
||||
.clickCancelSubscription()
|
||||
.subscriptionIsCancelled()
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package me.proton.core.plan.test.robot
|
||||
|
||||
public data class BillingCycle(
|
||||
val value: String,
|
||||
val monthlyPrice: Double
|
||||
) {
|
||||
public companion object {
|
||||
// Predefined payment period values
|
||||
public const val PAY_ANNUALLY: String = "Pay annually"
|
||||
public const val PAY_MONTHLY: String = "Pay monthly"
|
||||
}
|
||||
}
|
||||
|
||||
public data class Plan(
|
||||
val id: String,
|
||||
val name: String,
|
||||
val billingCycle: BillingCycle
|
||||
) {
|
||||
|
||||
override fun toString(): String {
|
||||
return "$name, ${billingCycle.value}" // Shows only Plan name in parametrized test
|
||||
}
|
||||
|
||||
public companion object {
|
||||
// Predefined Billing Cycles
|
||||
public val Free: Plan =
|
||||
Plan(
|
||||
"Free", "Free",
|
||||
BillingCycle(
|
||||
BillingCycle.PAY_MONTHLY,
|
||||
0.0
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -23,14 +23,14 @@ import me.proton.core.payment.presentation.view.ProtonPaymentButton
|
||||
import me.proton.core.paymentiap.test.robot.GPBottomSheetSubscribeRobot
|
||||
import me.proton.core.paymentiap.test.robot.PlayStoreSubscriptionsRobot
|
||||
import me.proton.core.plan.presentation.R
|
||||
import me.proton.core.plan.test.BillingCycle
|
||||
import me.proton.core.plan.test.BillingPlan
|
||||
import me.proton.core.presentation.ui.view.ProtonButton
|
||||
import me.proton.test.fusion.Fusion.byObject
|
||||
import me.proton.test.fusion.Fusion.device
|
||||
import me.proton.test.fusion.Fusion.view
|
||||
import me.proton.test.fusion.FusionConfig
|
||||
import me.proton.test.fusion.ui.common.enums.SwipeDirection
|
||||
import me.proton.test.fusion.ui.espresso.builders.OnView
|
||||
import okhttp3.internal.wait
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
public object SubscriptionRobot {
|
||||
@@ -67,12 +67,12 @@ public object SubscriptionRobot {
|
||||
view.withCustomMatcher(ViewMatchers.withSubstring("Get"))
|
||||
}
|
||||
|
||||
internal fun togglePlanItem(plan: Plan) {
|
||||
view.withId(R.id.title).withText(plan.name).scrollTo().click()
|
||||
internal fun togglePlanItem(billingPlan: BillingPlan) {
|
||||
view.withId(R.id.title).withText(billingPlan.name).scrollTo().click()
|
||||
}
|
||||
|
||||
internal fun getPlanButton(plan: Plan): OnView {
|
||||
val buttonText = FusionConfig.targetContext.getString(R.string.plans_get_proton, plan.name)
|
||||
internal fun getPlanButton(billingPlan: BillingPlan): OnView {
|
||||
val buttonText = FusionConfig.targetContext.getString(R.string.plans_get_proton, billingPlan.name)
|
||||
return view.instanceOf(ProtonPaymentButton::class.java).containsText(buttonText)
|
||||
}
|
||||
|
||||
@@ -80,31 +80,31 @@ public object SubscriptionRobot {
|
||||
return view.withText(R.string.plans_proton_for_free)
|
||||
}
|
||||
|
||||
private fun expandPlan(plan: Plan) {
|
||||
togglePlanItem(plan)
|
||||
private fun expandPlan(billingPlan: BillingPlan) {
|
||||
togglePlanItem(billingPlan)
|
||||
}
|
||||
|
||||
public fun selectExpandedPlan(plan: Plan): GPBottomSheetSubscribeRobot {
|
||||
public fun selectExpandedPlan(billingPlan: BillingPlan): GPBottomSheetSubscribeRobot {
|
||||
view.withId(R.id.scrollContent).hasDescendant(view.withId(R.id.plans)).swipe(SwipeDirection.Up)
|
||||
getPlanButton(plan).click()
|
||||
getPlanButton(billingPlan).click()
|
||||
return GPBottomSheetSubscribeRobot()
|
||||
}
|
||||
|
||||
public fun selectFreePlan() {
|
||||
view.withText("Free").await(timeout = 90.seconds) { checkIsDisplayed() }
|
||||
view.withText("Free").scrollTo().click()
|
||||
getPlanButton(Plan.Free).scrollTo().click()
|
||||
getPlanButton(BillingPlan.Free).scrollTo().click()
|
||||
}
|
||||
|
||||
public fun selectPlan(plan: Plan): GPBottomSheetSubscribeRobot {
|
||||
public fun selectPlan(billingPlan: BillingPlan): GPBottomSheetSubscribeRobot {
|
||||
planSelectionIsDisplayed()
|
||||
expandPlan(plan)
|
||||
selectExpandedPlan(plan)
|
||||
expandPlan(billingPlan)
|
||||
selectExpandedPlan(billingPlan)
|
||||
return GPBottomSheetSubscribeRobot()
|
||||
}
|
||||
|
||||
public fun togglePlan(plan: Plan) {
|
||||
togglePlanItem(plan)
|
||||
public fun togglePlan(billingPlan: BillingPlan) {
|
||||
togglePlanItem(billingPlan)
|
||||
}
|
||||
|
||||
public fun selectBillingCycle(cycle: BillingCycle): SubscriptionRobot {
|
||||
@@ -164,8 +164,8 @@ public object SubscriptionRobot {
|
||||
view.withId(R.id.price_cycle).withText(value).await { checkIsDisplayed() }
|
||||
}
|
||||
|
||||
public fun verifyCanGetPlan(plan: Plan) {
|
||||
getPlanButton(plan)
|
||||
public fun verifyCanGetPlan(billingPlan: BillingPlan) {
|
||||
getPlanButton(billingPlan)
|
||||
.scrollTo()
|
||||
.checkIsDisplayed()
|
||||
.checkIsEnabled()
|
||||
|
||||
@@ -141,5 +141,5 @@ public const val `json-simple version`: String = "1.1.1"
|
||||
public const val `turbine version`: String = "0.12.1"
|
||||
public const val `junit version`: String = "4.13.2"
|
||||
public const val `junit-ktx version`: String = "1.1.4"
|
||||
public const val `fusion version`: String = "1.0.1"
|
||||
public const val `fusion version`: String = "1.0.4"
|
||||
// endregion
|
||||
|
||||
Reference in New Issue
Block a user