diff options
| author | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2023-11-16 11:08:21 +0100 |
|---|---|---|
| committer | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2023-11-16 11:08:21 +0100 |
| commit | 04c6609948a770aed30491c66c4c6d779bc71c92 (patch) | |
| tree | 4184b4e7a8c8ebfe8c4273e9f472779ee8f7bae9 /android/app/src/androidTest | |
| parent | 67710f3e2ef57ecbe60c1bcb444ab047f11f79a5 (diff) | |
| parent | c8c896bc00b6b23ffaaf3a8708f03efb3ab3a0f2 (diff) | |
| download | mullvadvpn-04c6609948a770aed30491c66c4c6d779bc71c92.tar.xz mullvadvpn-04c6609948a770aed30491c66c4c6d779bc71c92.zip | |
Merge branch 'google-play-in-app-purchases-droid-277'
Diffstat (limited to 'android/app/src/androidTest')
3 files changed, 764 insertions, 11 deletions
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt index aec6c85595..e997ae29e4 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt @@ -1,21 +1,33 @@ package net.mullvad.mullvadvpn.compose.screen +import android.app.Activity import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import io.mockk.MockKAnnotations +import io.mockk.every import io.mockk.mockk import io.mockk.verify import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow import net.mullvad.mullvadvpn.compose.setContentWithTheme +import net.mullvad.mullvadvpn.compose.state.PaymentState +import net.mullvad.mullvadvpn.compose.test.PLAY_PAYMENT_INFO_ICON_TEST_TAG +import net.mullvad.mullvadvpn.lib.payment.model.PaymentProduct +import net.mullvad.mullvadvpn.lib.payment.model.PaymentStatus +import net.mullvad.mullvadvpn.lib.payment.model.ProductId +import net.mullvad.mullvadvpn.lib.payment.model.ProductPrice +import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult +import net.mullvad.mullvadvpn.util.toPaymentDialogData import net.mullvad.mullvadvpn.viewmodel.AccountUiState import net.mullvad.mullvadvpn.viewmodel.AccountViewModel import org.junit.Before import org.junit.Rule import org.junit.Test +@OptIn(ExperimentalMaterial3Api::class) class AccountScreenTest { @get:Rule val composeTestRule = createComposeRule() @@ -24,12 +36,12 @@ class AccountScreenTest { MockKAnnotations.init(this) } - @OptIn(ExperimentalMaterial3Api::class) @Test fun testDefaultState() { // Arrange composeTestRule.setContentWithTheme { AccountScreen( + showSitePayment = true, uiState = AccountUiState( deviceName = DUMMY_DEVICE_NAME, @@ -48,13 +60,13 @@ class AccountScreenTest { } } - @OptIn(ExperimentalMaterial3Api::class) @Test fun testManageAccountClick() { // Arrange val mockedClickHandler: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { AccountScreen( + showSitePayment = true, uiState = AccountUiState( deviceName = DUMMY_DEVICE_NAME, @@ -74,13 +86,13 @@ class AccountScreenTest { verify { mockedClickHandler.invoke() } } - @OptIn(ExperimentalMaterial3Api::class) @Test fun testRedeemVoucherClick() { // Arrange val mockedClickHandler: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { AccountScreen( + showSitePayment = true, uiState = AccountUiState( deviceName = DUMMY_DEVICE_NAME, @@ -100,13 +112,13 @@ class AccountScreenTest { verify { mockedClickHandler.invoke() } } - @OptIn(ExperimentalMaterial3Api::class) @Test fun testLogoutClick() { // Arrange val mockedClickHandler: () -> Unit = mockk(relaxed = true) composeTestRule.setContentWithTheme { AccountScreen( + showSitePayment = true, uiState = AccountUiState( deviceName = DUMMY_DEVICE_NAME, @@ -126,6 +138,220 @@ class AccountScreenTest { verify { mockedClickHandler.invoke() } } + @Test + fun testShowPurchaseCompleteDialog() { + // Arrange + composeTestRule.setContentWithTheme { + AccountScreen( + showSitePayment = true, + uiState = + AccountUiState.default() + .copy( + paymentDialogData = + PurchaseResult.Completed.Success.toPaymentDialogData() + ), + uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), + enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() + ) + } + + // Assert + composeTestRule.onNodeWithText("Time was successfully added").assertExists() + } + + @Test + fun testShowVerificationErrorDialog() { + // Arrange + composeTestRule.setContentWithTheme { + AccountScreen( + showSitePayment = true, + uiState = + AccountUiState.default() + .copy( + paymentDialogData = + PurchaseResult.Error.VerificationError(null).toPaymentDialogData() + ), + uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), + enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() + ) + } + + // Assert + composeTestRule.onNodeWithText("Verifying purchase").assertExists() + } + + @Test + fun testShowFetchProductsErrorDialog() { + // Arrange + composeTestRule.setContentWithTheme { + AccountScreen( + showSitePayment = true, + uiState = + AccountUiState.default() + .copy( + paymentDialogData = + PurchaseResult.Error.FetchProductsError(ProductId(""), null) + .toPaymentDialogData() + ), + uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), + enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() + ) + } + + // Assert + composeTestRule.onNodeWithText("Google Play unavailable").assertExists() + } + + @Test + fun testShowBillingErrorPaymentButton() { + // Arrange + composeTestRule.setContentWithTheme { + AccountScreen( + showSitePayment = true, + uiState = + AccountUiState.default().copy(billingPaymentState = PaymentState.Error.Billing), + uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), + enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() + ) + } + + // Assert + composeTestRule.onNodeWithText("Add 30 days time").assertExists() + } + + @Test + fun testShowBillingPaymentAvailable() { + // Arrange + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.status } returns null + composeTestRule.setContentWithTheme { + AccountScreen( + showSitePayment = true, + uiState = + AccountUiState.default() + .copy( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), + enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() + ) + } + + // Assert + composeTestRule.onNodeWithText("Add 30 days time ($10)").assertExists() + } + + @Test + fun testShowPendingPayment() { + // Arrange + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.status } returns PaymentStatus.PENDING + composeTestRule.setContentWithTheme { + AccountScreen( + showSitePayment = true, + uiState = + AccountUiState.default() + .copy( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), + enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() + ) + } + + // Assert + composeTestRule.onNodeWithText("Google Play payment pending").assertExists() + } + + @Test + fun testShowPendingPaymentInfoDialog() { + // Arrange + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.status } returns PaymentStatus.PENDING + composeTestRule.setContentWithTheme { + AccountScreen( + showSitePayment = true, + uiState = + AccountUiState.default() + .copy( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), + enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() + ) + } + + // Act + composeTestRule.onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).performClick() + + // Assert + composeTestRule + .onNodeWithText( + "We are currently verifying your purchase, this might take some time. Your time will be added if the verification is successful." + ) + .assertExists() + } + + @Test + fun testShowVerificationInProgress() { + // Arrange + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.status } returns PaymentStatus.VERIFICATION_IN_PROGRESS + composeTestRule.setContentWithTheme { + AccountScreen( + showSitePayment = true, + uiState = + AccountUiState.default() + .copy( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), + enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() + ) + } + + // Assert + composeTestRule.onNodeWithText("Verifying purchase").assertExists() + } + + @Test + fun testOnPurchaseBillingProductClick() { + // Arrange + val clickHandler: (ProductId, () -> Activity) -> Unit = mockk(relaxed = true) + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.productId } returns ProductId("PRODUCT_ID") + every { mockPaymentProduct.status } returns null + composeTestRule.setContentWithTheme { + AccountScreen( + showSitePayment = true, + uiState = + AccountUiState.default() + .copy( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + onPurchaseBillingProductClick = clickHandler, + uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(), + enterTransitionEndAction = MutableSharedFlow<Unit>().asSharedFlow() + ) + } + + // Act + composeTestRule.onNodeWithText("Add 30 days time ($10)").performClick() + + // Assert + verify { clickHandler.invoke(ProductId("PRODUCT_ID"), any()) } + } + companion object { private const val DUMMY_DEVICE_NAME = "fake_name" private const val DUMMY_ACCOUNT_NUMBER = "fake_number" diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt index b0198316e3..28e2519c81 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt @@ -1,16 +1,28 @@ package net.mullvad.mullvadvpn.compose.screen +import android.app.Activity import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import io.mockk.MockKAnnotations +import io.mockk.every import io.mockk.mockk import io.mockk.verify import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asSharedFlow import net.mullvad.mullvadvpn.compose.setContentWithTheme import net.mullvad.mullvadvpn.compose.state.OutOfTimeUiState +import net.mullvad.mullvadvpn.compose.state.PaymentState +import net.mullvad.mullvadvpn.compose.test.PLAY_PAYMENT_INFO_ICON_TEST_TAG +import net.mullvad.mullvadvpn.lib.payment.model.PaymentProduct +import net.mullvad.mullvadvpn.lib.payment.model.PaymentStatus +import net.mullvad.mullvadvpn.lib.payment.model.ProductId +import net.mullvad.mullvadvpn.lib.payment.model.ProductPrice +import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult import net.mullvad.mullvadvpn.model.TunnelState +import net.mullvad.mullvadvpn.util.toPaymentDialogData import net.mullvad.mullvadvpn.viewmodel.OutOfTimeViewModel import org.junit.Before import org.junit.Rule @@ -174,4 +186,232 @@ class OutOfTimeScreenTest { // Assert verify(exactly = 1) { mockClickListener.invoke() } } + + @Test + fun testShowPurchaseCompleteDialog() { + // Arrange + composeTestRule.setContentWithTheme { + OutOfTimeScreen( + showSitePayment = true, + uiState = + OutOfTimeUiState( + paymentDialogData = PurchaseResult.Completed.Success.toPaymentDialogData() + ), + uiSideEffect = MutableStateFlow(OutOfTimeViewModel.UiSideEffect.OpenConnectScreen), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> } + ) + } + + // Assert + composeTestRule.onNodeWithText("Time was successfully added").assertExists() + } + + @Test + fun testShowVerificationErrorDialog() { + // Arrange + composeTestRule.setContentWithTheme { + OutOfTimeScreen( + showSitePayment = true, + uiState = + OutOfTimeUiState( + paymentDialogData = + PurchaseResult.Error.VerificationError(null).toPaymentDialogData() + ), + uiSideEffect = MutableStateFlow(OutOfTimeViewModel.UiSideEffect.OpenConnectScreen), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> } + ) + } + + // Assert + composeTestRule.onNodeWithText("Verifying purchase").assertExists() + } + + @Test + fun testShowFetchProductsErrorDialog() { + // Arrange + composeTestRule.setContentWithTheme { + OutOfTimeScreen( + showSitePayment = true, + uiState = + OutOfTimeUiState() + .copy( + paymentDialogData = + PurchaseResult.Error.FetchProductsError(ProductId(""), null) + .toPaymentDialogData() + ), + uiSideEffect = MutableSharedFlow<OutOfTimeViewModel.UiSideEffect>().asSharedFlow() + ) + } + + // Assert + composeTestRule.onNodeWithText("Google Play unavailable").assertExists() + } + + @Test + fun testShowBillingErrorPaymentButton() { + // Arrange + composeTestRule.setContentWithTheme { + OutOfTimeScreen( + showSitePayment = true, + uiState = OutOfTimeUiState().copy(billingPaymentState = PaymentState.Error.Billing), + uiSideEffect = MutableSharedFlow<OutOfTimeViewModel.UiSideEffect>().asSharedFlow(), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> } + ) + } + + // Assert + composeTestRule.onNodeWithText("Add 30 days time").assertExists() + } + + @Test + fun testShowBillingPaymentAvailable() { + // Arrange + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.status } returns null + composeTestRule.setContentWithTheme { + OutOfTimeScreen( + showSitePayment = true, + uiState = + OutOfTimeUiState( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableStateFlow(OutOfTimeViewModel.UiSideEffect.OpenConnectScreen), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> } + ) + } + + // Assert + composeTestRule.onNodeWithText("Add 30 days time ($10)").assertExists() + } + + @Test + fun testShowPendingPayment() { + // Arrange + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.status } returns PaymentStatus.PENDING + composeTestRule.setContentWithTheme { + OutOfTimeScreen( + showSitePayment = true, + uiState = + OutOfTimeUiState() + .copy( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableSharedFlow<OutOfTimeViewModel.UiSideEffect>().asSharedFlow() + ) + } + + // Assert + composeTestRule.onNodeWithText("Google Play payment pending").assertExists() + } + + @Test + fun testShowPendingPaymentInfoDialog() { + // Arrange + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.status } returns PaymentStatus.PENDING + composeTestRule.setContentWithTheme { + OutOfTimeScreen( + showSitePayment = true, + uiState = + OutOfTimeUiState() + .copy( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableSharedFlow<OutOfTimeViewModel.UiSideEffect>().asSharedFlow() + ) + } + + // Act + composeTestRule.onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).performClick() + + // Assert + composeTestRule + .onNodeWithText( + "We are currently verifying your purchase, this might take some time. Your time will be added if the verification is successful." + ) + .assertExists() + } + + @Test + fun testShowVerificationInProgress() { + // Arrange + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.status } returns PaymentStatus.VERIFICATION_IN_PROGRESS + composeTestRule.setContentWithTheme { + OutOfTimeScreen( + showSitePayment = true, + uiState = + OutOfTimeUiState() + .copy( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableSharedFlow<OutOfTimeViewModel.UiSideEffect>().asSharedFlow() + ) + } + + // Assert + composeTestRule.onNodeWithText("Verifying purchase").assertExists() + } + + @Test + fun testOnPurchaseBillingProductClick() { + // Arrange + val clickHandler: (ProductId, () -> Activity) -> Unit = mockk(relaxed = true) + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.productId } returns ProductId("PRODUCT_ID") + every { mockPaymentProduct.status } returns null + composeTestRule.setContentWithTheme { + OutOfTimeScreen( + showSitePayment = true, + uiState = + OutOfTimeUiState( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableStateFlow(OutOfTimeViewModel.UiSideEffect.OpenConnectScreen), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onPurchaseBillingProductClick = clickHandler + ) + } + + // Act + composeTestRule.onNodeWithText("Add 30 days time ($10)").performClick() + + // Assert + verify { clickHandler(ProductId("PRODUCT_ID"), any()) } + } } diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt index 8331794cab..a54c41c20d 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt @@ -1,15 +1,27 @@ package net.mullvad.mullvadvpn.compose.screen +import android.app.Activity import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import io.mockk.MockKAnnotations +import io.mockk.every import io.mockk.mockk import io.mockk.verify import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asSharedFlow import net.mullvad.mullvadvpn.compose.setContentWithTheme +import net.mullvad.mullvadvpn.compose.state.PaymentState import net.mullvad.mullvadvpn.compose.state.WelcomeUiState +import net.mullvad.mullvadvpn.compose.test.PLAY_PAYMENT_INFO_ICON_TEST_TAG +import net.mullvad.mullvadvpn.lib.payment.model.PaymentProduct +import net.mullvad.mullvadvpn.lib.payment.model.PaymentStatus +import net.mullvad.mullvadvpn.lib.payment.model.ProductId +import net.mullvad.mullvadvpn.lib.payment.model.ProductPrice +import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult +import net.mullvad.mullvadvpn.util.toPaymentDialogData import net.mullvad.mullvadvpn.viewmodel.WelcomeViewModel import org.junit.Before import org.junit.Rule @@ -35,7 +47,9 @@ class WelcomeScreenTest { onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {} + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} ) } @@ -58,7 +72,9 @@ class WelcomeScreenTest { onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {} + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} ) } @@ -87,7 +103,9 @@ class WelcomeScreenTest { onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {} + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} ) } @@ -108,7 +126,9 @@ class WelcomeScreenTest { onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {} + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} ) } @@ -129,7 +149,9 @@ class WelcomeScreenTest { onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = mockClickListener + openConnectScreen = mockClickListener, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} ) } @@ -150,7 +172,9 @@ class WelcomeScreenTest { onRedeemVoucherClick = {}, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {} + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} ) } @@ -174,7 +198,9 @@ class WelcomeScreenTest { onRedeemVoucherClick = mockClickListener, onSettingsClick = {}, onAccountClick = {}, - openConnectScreen = {} + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} ) } @@ -184,4 +210,265 @@ class WelcomeScreenTest { // Assert verify(exactly = 1) { mockClickListener.invoke() } } + + @Test + fun testShowPurchaseCompleteDialog() { + // Arrange + composeTestRule.setContentWithTheme { + WelcomeScreen( + showSitePayment = true, + uiState = + WelcomeUiState( + paymentDialogData = PurchaseResult.Completed.Success.toPaymentDialogData() + ), + uiSideEffect = MutableStateFlow(WelcomeViewModel.UiSideEffect.OpenConnectScreen), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} + ) + } + + // Assert + composeTestRule.onNodeWithText("Time was successfully added").assertExists() + } + + @Test + fun testShowVerificationErrorDialog() { + // Arrange + composeTestRule.setContentWithTheme { + WelcomeScreen( + showSitePayment = true, + uiState = + WelcomeUiState( + paymentDialogData = + PurchaseResult.Error.VerificationError(null).toPaymentDialogData() + ), + uiSideEffect = MutableStateFlow(WelcomeViewModel.UiSideEffect.OpenConnectScreen), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} + ) + } + + // Assert + composeTestRule.onNodeWithText("Verifying purchase").assertExists() + } + + @Test + fun testShowFetchProductsErrorDialog() { + // Arrange + composeTestRule.setContentWithTheme { + WelcomeScreen( + showSitePayment = true, + uiState = + WelcomeUiState() + .copy( + paymentDialogData = + PurchaseResult.Error.FetchProductsError(ProductId(""), null) + .toPaymentDialogData() + ), + uiSideEffect = MutableSharedFlow<WelcomeViewModel.UiSideEffect>().asSharedFlow(), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} + ) + } + + // Assert + composeTestRule.onNodeWithText("Google Play unavailable").assertExists() + } + + @Test + fun testShowBillingErrorPaymentButton() { + // Arrange + composeTestRule.setContentWithTheme { + WelcomeScreen( + showSitePayment = true, + uiState = WelcomeUiState().copy(billingPaymentState = PaymentState.Error.Billing), + uiSideEffect = MutableSharedFlow<WelcomeViewModel.UiSideEffect>().asSharedFlow(), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onClosePurchaseResultDialog = {}, + onPurchaseBillingProductClick = { _, _ -> } + ) + } + + // Assert + composeTestRule.onNodeWithText("Add 30 days time").assertExists() + } + + @Test + fun testShowBillingPaymentAvailable() { + // Arrange + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.status } returns null + composeTestRule.setContentWithTheme { + WelcomeScreen( + showSitePayment = true, + uiState = + WelcomeUiState( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableStateFlow(WelcomeViewModel.UiSideEffect.OpenConnectScreen), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} + ) + } + + // Assert + composeTestRule.onNodeWithText("Add 30 days time ($10)").assertExists() + } + + @Test + fun testShowPendingPayment() { + // Arrange + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.status } returns PaymentStatus.PENDING + composeTestRule.setContentWithTheme { + WelcomeScreen( + showSitePayment = true, + uiState = + WelcomeUiState() + .copy( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableSharedFlow<WelcomeViewModel.UiSideEffect>().asSharedFlow(), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} + ) + } + + // Assert + composeTestRule.onNodeWithText("Google Play payment pending").assertExists() + } + + @Test + fun testShowPendingPaymentInfoDialog() { + // Arrange + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.status } returns PaymentStatus.PENDING + composeTestRule.setContentWithTheme { + WelcomeScreen( + showSitePayment = true, + uiState = + WelcomeUiState() + .copy( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableSharedFlow<WelcomeViewModel.UiSideEffect>().asSharedFlow(), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} + ) + } + + // Act + composeTestRule.onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).performClick() + + // Assert + composeTestRule + .onNodeWithText( + "We are currently verifying your purchase, this might take some time. Your time will be added if the verification is successful." + ) + .assertExists() + } + + @Test + fun testShowVerificationInProgress() { + // Arrange + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.status } returns PaymentStatus.VERIFICATION_IN_PROGRESS + composeTestRule.setContentWithTheme { + WelcomeScreen( + showSitePayment = true, + uiState = + WelcomeUiState() + .copy( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableSharedFlow<WelcomeViewModel.UiSideEffect>().asSharedFlow(), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onPurchaseBillingProductClick = { _, _ -> }, + onClosePurchaseResultDialog = {} + ) + } + + // Assert + composeTestRule.onNodeWithText("Verifying purchase").assertExists() + } + + @Test + fun testOnPurchaseBillingProductClick() { + // Arrange + val clickHandler: (ProductId, () -> Activity) -> Unit = mockk(relaxed = true) + val mockPaymentProduct: PaymentProduct = mockk() + every { mockPaymentProduct.price } returns ProductPrice("$10") + every { mockPaymentProduct.productId } returns ProductId("PRODUCT_ID") + every { mockPaymentProduct.status } returns null + composeTestRule.setContentWithTheme { + WelcomeScreen( + showSitePayment = true, + uiState = + WelcomeUiState( + billingPaymentState = + PaymentState.PaymentAvailable(listOf(mockPaymentProduct)) + ), + uiSideEffect = MutableStateFlow(WelcomeViewModel.UiSideEffect.OpenConnectScreen), + onSitePaymentClick = {}, + onRedeemVoucherClick = {}, + onSettingsClick = {}, + onAccountClick = {}, + openConnectScreen = {}, + onPurchaseBillingProductClick = clickHandler, + onClosePurchaseResultDialog = {} + ) + } + + // Act + composeTestRule.onNodeWithText("Add 30 days time ($10)").performClick() + + // Assert + verify { clickHandler(ProductId("PRODUCT_ID"), any()) } + } } |
