Skip to content

Commit

Permalink
Merge pull request #1034 from ILIYANGERMANOV/develop
Browse files Browse the repository at this point in the history
Revamp UI tests
  • Loading branch information
ILIYANGERMANOV committed Jun 11, 2022
2 parents a7f21ef + 57521a3 commit 2845f7c
Show file tree
Hide file tree
Showing 51 changed files with 2,363 additions and 2,446 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import androidx.work.testing.WorkManagerTestInitHelper
import com.ivy.frp.test.TestIdlingResource
import com.ivy.frp.test.TestingContext
import com.ivy.frp.view.navigation.Navigation
import com.ivy.wallet.compose.helpers.OnboardingFlow
import com.ivy.wallet.io.network.IvySession
import com.ivy.wallet.io.persistence.IvyRoomDatabase
import com.ivy.wallet.io.persistence.SharedPrefs
Expand All @@ -35,6 +36,7 @@ import org.junit.Before
import org.junit.Rule
import javax.inject.Inject

typealias IvyComposeTestRule = AndroidComposeTestRule<ActivityScenarioRule<RootActivity>, RootActivity>

@HiltAndroidTest
abstract class IvyComposeTest {
Expand Down Expand Up @@ -125,10 +127,10 @@ abstract class IvyComposeTest {
attempt: Int = 0,
maxAttempts: Int = 3,
firstFailure: Throwable? = null,
test: () -> Unit
test: OnboardingFlow.() -> Unit
) {
try {
test()
OnboardingFlow(composeTestRule).test()
} catch (e: Throwable) {
if (attempt < maxAttempts) {
//reset state && retry test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,77 @@
package com.ivy.wallet.compose.helpers

import androidx.activity.ComponentActivity
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.test.*
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.ext.junit.rules.ActivityScenarioRule
import com.ivy.wallet.compose.IvyComposeTestRule

class AccountModal<A : ComponentActivity>(
private val composeTestRule: AndroidComposeTestRule<ActivityScenarioRule<A>, A>
) {
val ivyColorPicker = IvyColorPicker(composeTestRule)
val chooseIconFlow = ChooseIconFlow(composeTestRule)
val currencyPicker = CurrencyPicker(composeTestRule)
class AccountModal(
private val composeTestRule: IvyComposeTestRule
) : ColorPicker<AccountModal>, IconPicker<AccountModal>,
CurrencyPicker<AccountModal>, AmountInput<AccountModal> {

fun enterTitle(
title: String
) {
): AccountModal {
composeTestRule.onNodeWithTag("base_input")
.performTextReplacement(title)
return this
}

fun clickBalance() {
private fun clickBalance(): IvyAmountInput {
composeTestRule
.onNode(hasTestTag("amount_balance"))
.performClick()
return IvyAmountInput(composeTestRule)
}

fun chooseCurrency() {
private fun clickCurrency(): IvyCurrencyPicker {
composeTestRule.onNodeWithTag("account_modal_currency")
.performClick()
return IvyCurrencyPicker(composeTestRule)
}

fun clickSave() {
fun <N> clickSave(next: N): N {
composeTestRule
.onNode(hasText("Save"))
.performClick()
return next
}

fun clickAdd() {
fun clickAdd(): AccountsTab {
composeTestRule
.onNode(hasText("Add"))
.performClick()
return AccountsTab(composeTestRule)
}

fun tapIncludeInBalance() {
fun tapIncludeInBalance(): AccountModal {
composeTestRule.onNodeWithText("Include account")
.performClick()
return this
}

override fun chooseColor(color: Color): AccountModal {
IvyColorPicker(composeTestRule).chooseColor(color)
return this
}

override fun chooseIcon(icon: String): AccountModal {
ChooseIconFlow(composeTestRule).chooseIcon(icon)
return this
}


override fun chooseCurrency(currencyCode: String): AccountModal {
clickCurrency()
.chooseCurrency(currencyCode)
return this
}

override fun enterAmount(number: String): AccountModal {
return clickBalance()
.enterNumber(
number = number,
next = this
)
}
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
package com.ivy.wallet.compose.helpers

import android.icu.util.Currency
import androidx.activity.ComponentActivity
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.test.*
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.ext.junit.rules.ActivityScenarioRule
import com.ivy.wallet.compose.IvyComposeTestRule
import com.ivy.wallet.compose.hideKeyboard
import com.ivy.wallet.compose.printTree
import com.ivy.wallet.ui.theme.Ivy

class AccountsTab<A : ComponentActivity>(
private val composeTestRule: AndroidComposeTestRule<ActivityScenarioRule<A>, A>
) {
private val mainBottomBar = MainBottomBar(composeTestRule)
private val accountModal = AccountModal(composeTestRule)
private val amountInput = AmountInput(composeTestRule)
class AccountsTab(
private val composeTestRule: IvyComposeTestRule
) : MainBottomBar<AccountModal>(composeTestRule) {

fun assertAccountBalance(
account: String,
balance: String,
balanceDecimal: String,
currency: String = "USD",
baseCurrencyEquivalent: Boolean = false
) {
): AccountsTab {
composeTestRule.printTree()

composeTestRule.onNode(
Expand All @@ -40,18 +34,22 @@ class AccountsTab<A : ComponentActivity>(
} else {
baseCurrencyBalanceRow.assertDoesNotExist()
}

return this
}

fun clickAccount(
account: String
) {
): ItemStatisticScreen {
composeTestRule.onNode(hasText(account)).performClick()
return ItemStatisticScreen(composeTestRule)
}

fun assertAccountNotExists(
account: String
) {
): AccountsTab {
composeTestRule.onNode(hasText(account)).assertDoesNotExist()
return this
}

fun addAccount(
Expand All @@ -60,38 +58,33 @@ class AccountsTab<A : ComponentActivity>(
icon: String? = null,
currency: String? = null,
initialBalance: String? = null
) {
mainBottomBar.clickAddFAB()

accountModal.apply {
enterTitle(name)

): AccountsTab = clickAddFAB(next = AccountModal(composeTestRule))
.enterTitle(name)
.apply {
composeTestRule.hideKeyboard()

ivyColorPicker.chooseColor(color = color)

}.chooseColor(color = color)
.apply {
if (icon != null) {
chooseIconFlow.chooseIcon(icon)
chooseIcon(icon)
}

}
.apply {
if (currency != null) {
chooseCurrency()
currencyPicker.searchAndSelect(Currency.getInstance(currency))
currencyPicker.modalSave()
chooseCurrency(currency)
}


}.apply {
if (initialBalance != null) {
clickBalance()
amountInput.enterNumber(initialBalance)
enterAmount(initialBalance)
}
}.clickAdd()

clickAdd()
}
}

fun clickReorder() {
fun clickReorder(): ReorderModal {
composeTestRule.onNodeWithTag("reorder_button")
.performClick()
return ReorderModal(composeTestRule)
}

override fun clickAddFAB(): AccountModal {
return clickAddFAB(next = AccountModal(composeTestRule))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.ivy.wallet.compose.helpers

import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.onNodeWithText
import com.ivy.wallet.compose.IvyComposeTestRule
import com.ivy.wallet.compose.clickWithRetry
import com.ivy.wallet.compose.performClickWithRetry

class AddFABMenu(
private val composeTestRule: IvyComposeTestRule
) {
fun clickAddIncome(): TransactionScreen {
composeTestRule.clickWithRetry(
node = composeTestRule.onNode(hasText("ADD INCOME")),
maxRetries = 3
)
return TransactionScreen(composeTestRule)
}

fun clickAddExpense(): TransactionScreen {
composeTestRule.onNode(hasText("ADD EXPENSE"))
.performClickWithRetry(composeTestRule)
return TransactionScreen(composeTestRule)
}

fun clickAddTransfer(): TransactionScreen {
composeTestRule.onNode(hasText("ACCOUNT TRANSFER"))
.performClickWithRetry(composeTestRule)
return TransactionScreen(composeTestRule)
}

fun clickAddPlannedPayment(): EditPlannedScreen {
composeTestRule.onNodeWithText("Add planned payment")
.performClickWithRetry(composeTestRule)
return EditPlannedScreen(composeTestRule)
}
}
Original file line number Diff line number Diff line change
@@ -1,52 +1,65 @@
package com.ivy.wallet.compose.helpers

import androidx.activity.ComponentActivity
import androidx.compose.ui.test.*
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.ext.junit.rules.ActivityScenarioRule
import com.ivy.wallet.compose.IvyComposeTestRule

class BudgetModal<A : ComponentActivity>(
private val composeTestRule: AndroidComposeTestRule<ActivityScenarioRule<A>, A>
) {
private val amountInput = AmountInput(composeTestRule)
class BudgetModal(
private val composeTestRule: IvyComposeTestRule
) : AmountInput<BudgetModal>, DeleteItem<BudgetsScreen> {
private val amountInput = IvyAmountInput(composeTestRule)

fun enterName(budgetName: String) {
fun enterName(budgetName: String): BudgetModal {
composeTestRule.onNodeWithTag("base_input")
.performTextReplacement(budgetName)
return this
}

fun enterAmount(amount: String) {
private fun clickBudgetAmount(): IvyAmountInput {
composeTestRule.onNodeWithTag("amount_balance")
.performClick()

amountInput.enterNumber(amount)
return IvyAmountInput(composeTestRule)
}

fun clickCategory(category: String) {
fun clickCategory(category: String): BudgetModal {
composeTestRule.onNode(
hasText(category)
.and(hasAnyAncestor(hasTestTag("budget_categories_row"))),
useUnmergedTree = true
).performClick()
return this
}

fun clickAdd() {
fun clickAdd(): BudgetsScreen {
composeTestRule.onNodeWithText("Add")
.performClick()
return BudgetsScreen(composeTestRule)
}

fun clickSave() {
fun clickSave(): BudgetsScreen {
composeTestRule.onNodeWithText("Save")
.performClick()
return BudgetsScreen(composeTestRule)
}

fun clickDelete() {
private fun clickDelete(): DeleteConfirmationModal {
composeTestRule.onNodeWithTag("modal_delete")
.performClick()
return DeleteConfirmationModal(composeTestRule)
}

fun clickClose() {
fun clickClose(): BudgetsScreen {
composeTestRule.onNodeWithContentDescription("close")
.performClick()
return BudgetsScreen(composeTestRule)
}

override fun enterAmount(number: String): BudgetModal {
return clickBudgetAmount()
.enterNumber(number, next = this)
}

override fun deleteWithConfirmation(): BudgetsScreen {
return clickDelete()
.confirmDelete(next = BudgetsScreen(composeTestRule))
}
}
Loading

0 comments on commit 2845f7c

Please sign in to comment.