Skip to content
This repository has been archived by the owner on Jan 11, 2024. It is now read-only.

Added UI/Integration tests for creating Accounts, Accounts list, Account details and Accounts Task mgmt. features #195

Open
wants to merge 2 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ android:
- extra-google-m2repository
- extra-android-m2repository

script: "./gradlew build --stacktrace"
script: "./gradlew build --stacktrace"
"./gradlew build connectedAndroidTest --stacktrace"
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.apache.fineract.ui.online.accounts

import androidx.test.espresso.Espresso
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.contrib.DrawerActions
import androidx.test.espresso.contrib.NavigationViewActions
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import org.apache.fineract.R
import org.apache.fineract.ui.adapters.AccountsAdapter
import org.apache.fineract.ui.online.DashboardActivity
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith


/**
* Created by Varun Jain on 21/8/2021.
*/

@RunWith(AndroidJUnit4::class)
class AccountsListFragmentAndroidTest {

@get: Rule
val activityRule = ActivityTestRule<DashboardActivity>(DashboardActivity::class.java)

@Test
fun launchAccountListFragmentAndRvItemClickCheck() {

//Open drawer
Espresso.onView(ViewMatchers.withId(R.id.drawer_layout))
.perform(DrawerActions.open())

// Navigate to Teller list fragment
Espresso.onView(ViewMatchers.withId(R.id.nav_view))
.perform(NavigationViewActions.navigateTo(R.id.item_accounts))

//Click on teller item
Espresso.onView(ViewMatchers.withId(R.id.rvAccount)).perform(
RecyclerViewActions.actionOnItem<AccountsAdapter.ViewHolder>(
ViewMatchers.hasDescendant(ViewMatchers.withText("account identifier")),
ViewActions.click()
)
)

//Assert if thw item has been displayed correctly
Espresso.onView(ViewMatchers.withId(R.id.tvIdentifierAccount))
.check(ViewAssertions.matches(ViewMatchers.withText("account identifier")))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package org.apache.fineract.ui.online.accounts

import androidx.test.espresso.Espresso
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.contrib.DrawerActions
import androidx.test.espresso.contrib.NavigationViewActions
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import org.apache.fineract.R
import org.apache.fineract.couchbase.SynchronizationManager
import org.apache.fineract.data.models.accounts.Account
import org.apache.fineract.ui.adapters.AccountsAdapter
import org.apache.fineract.ui.online.DashboardActivity
import org.apache.fineract.utils.toDataClass
import org.junit.Assert
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

/**
* Created by Varun Jain on 21/8/2021.
*/

@RunWith(AndroidJUnit4::class)
class ChangeAccountStatusAndroidTest {

@get:Rule
val activityRule = ActivityTestRule<DashboardActivity>(DashboardActivity::class.java)

lateinit var synchronizationManager: SynchronizationManager

@Before
fun before() {
synchronizationManager =
SynchronizationManager(InstrumentationRegistry.getInstrumentation().context)
}

@Test
fun testIfAccountStatusChangedSuccessfully() {

//Open drawer
Espresso.onView(ViewMatchers.withId(R.id.drawer_layout))
.perform(DrawerActions.open())

// Navigate to Account list fragment
Espresso.onView(ViewMatchers.withId(R.id.nav_view))
.perform(NavigationViewActions.navigateTo(R.id.item_accounts))

//Click on recyclerView item
Espresso.onView(ViewMatchers.withId(R.id.rvAccount)).perform(
RecyclerViewActions.actionOnItem<AccountsAdapter.ViewHolder>(
ViewMatchers.hasDescendant(ViewMatchers.withText("account identifier")),
ViewActions.click()
)
)

//Assert if the item has been displayed correctly
Espresso.onView(ViewMatchers.withId(R.id.tvIdentifierAccount))
.check(ViewAssertions.matches(ViewMatchers.withText("account identifier")))

// Launch the Bottom sheet and click on the change Task Icon
Espresso.onView(ViewMatchers.withId(R.id.llTasksAccountDetails))
.perform(ViewActions.click())

// get current Account model from the synchronization manager
val mapItem = synchronizationManager.getDocumentForTest(
"account identifier",
InstrumentationRegistry.getInstrumentation().context
)

val account = mapItem.toDataClass<Account>()
val prevStatus = account.state

// click on the icon to change the account status
Espresso.onView(ViewMatchers.withId(R.id.ivAccountTask))
.perform(ViewActions.click())

Espresso.onView(ViewMatchers.withId(R.id.etCommentAccountTasks))
.perform(ViewActions.typeText("Changing state of this account"))
.perform(ViewActions.closeSoftKeyboard())

// confirm Task change operation
Espresso.onView(ViewMatchers.withId(R.id.btnSubmitAccountTask))
.perform(ViewActions.click())

// assert if the account status was changed successfully
when (prevStatus) {
Account.State.LOCKED -> {
Assert.assertEquals(account.state, Account.State.LOCKED)
}
Account.State.OPEN -> {
Assert.assertEquals(account.state, Account.State.OPEN)
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package org.apache.fineract.ui.online.accounts

import android.content.Intent
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.*
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.matcher.RootMatchers.isDialog
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import org.apache.fineract.R
import org.apache.fineract.couchbase.SynchronizationManager
import org.apache.fineract.data.models.accounts.Account
import org.apache.fineract.data.models.accounts.AccountType
import org.apache.fineract.ui.adapters.NameListAdapter
import org.apache.fineract.ui.online.accounting.accounts.AccountAction
import org.apache.fineract.ui.online.accounting.accounts.createaccount.CreateAccountActivity
import org.apache.fineract.utils.Constants
import org.apache.fineract.utils.toDataClass
import org.junit.*
import org.junit.runner.RunWith

/**
* Created by Varun Jain on 21/8/2021.
*/

@RunWith(AndroidJUnit4::class)
class CreateAccountActivityAndroidTest {

@get:Rule
var activityTestRule =
ActivityTestRule<CreateAccountActivity>(CreateAccountActivity::class.java, false, false)

lateinit var synchronizationManager: SynchronizationManager

@Before
fun before() {

val intent = Intent().apply {
putExtra(Constants.ACCOUNT_ACTION, AccountAction.CREATE)
}
activityTestRule.launchActivity(intent)
synchronizationManager =
SynchronizationManager(InstrumentationRegistry.getInstrumentation().context)
}

@Test
fun isCreateAccountStepVisible() {
onView(withId(R.id.slCreateAccount))
.check(matches(isDisplayed()))
}

@Test
fun createAccountTest() {

// Filling all the details in Account Details Step fragment
onView(withId(R.id.etIdentifierAccountDetailsStep))
.perform(typeText("test account"))
onView(withId(R.id.etNameAccountDetailsStep))
.perform(typeText("test name"))
onView(withId(R.id.etAltAccountNumAccountDetailsStep))
.perform(typeText("alternate account number"))
onView(withId(R.id.etLedgerAccountDetailsStep))
.perform(typeText("test Ledger"))
onView(withId(R.id.scrollViewAccountDetailsStep))
.perform(swipeUp())
onView(withId(R.id.etRefAccountNumAccountDetailsStep))
.perform(typeText("test Reference account number"))
onView(withId(R.id.etBalanceAccountDetailsStep))
.perform(typeText("1000"))
.perform(closeSoftKeyboard())

// Navigate to the next step
onView(withText("NEXT")).perform(click())

// Create the Holders
onView(withId(R.id.ivAddHolder))
.perform(click())
onView(withId(R.id.etNewHolder))
.perform(typeText("Account"))
onView(withId(R.id.scrollViewAddAccountHolderStep))
onView(withId(R.id.btnAddHolder))
.perform(click())

// Edit an Account assignment
onView(withId(R.id.iv_edit))
.perform(click())
onView(withId(R.id.etNewHolder))
.perform(typeText(" test holder"))
onView(withId(R.id.scrollViewAddAccountHolderStep))
.perform(swipeUp())
onView(withId(R.id.btnAddHolder))
.perform(click())

// Delete a Account assignment
onView(withId(R.id.iv_delete))
.perform(click())

// Dismiss the Delete dialog
onView(withText("DELETE")).inRoot(isDialog()).check(matches(isDisplayed())).perform(pressBack());

// Navigate to the next step
onView(withText("NEXT")).perform(click())

// Create the Signature Authorities
onView(withId(R.id.ivAddSignatureAuthorities))
.perform(click())
onView(withId(R.id.etNewSignatureAuthorities))
.perform(typeText("test signature authority"))
onView(withId(R.id.scrollViewAddAccountSignatureAuthorityStep))
onView(withId(R.id.btnAddSignatureAuthority))
.perform(click())

// Navigate to the next step
onView(withText("NEXT")).perform(click())

// Test if the account Review Step is populated with the correct values
onView(withId(R.id.tvIdentifierAccountStepReview)).check(matches(withText("test account")))
onView(withId(R.id.tvTypeAccountStepReview)).check(matches(withText(AccountType.ASSET.toString())))
onView(withId(R.id.tvNameAccountStepReview)).check(matches(withText("test name")))
onView(withId(R.id.scrollViewAccountReviewStep))
.perform(swipeUp())
onView(withId(R.id.rvHoldersAccountStepReview))
.perform(
RecyclerViewActions.actionOnItem<NameListAdapter.ViewHolder>(
hasDescendant(withText("Account test holder")), click()
)
)
onView(withId(R.id.rvSignatureAuthoritiesAccountStepReview))
.perform(
RecyclerViewActions.actionOnItem<NameListAdapter.ViewHolder>(
hasDescendant(withText("test signature authority")), click()
)
)
onView(withId(R.id.tvRefAccountStepReview)).check(matches(withText("test Reference account number")))
onView(withId(R.id.tvLedgerAccountStepReview)).check(matches(withText("test Ledger")))
onView(withId(R.id.tvAltAccountNoAccountStepReview)).check(matches(withText("alternate account number")))

// Complete creating the account
onView(withText("COMPLETE")).perform(click())

// assert if the account was created successfully
val mapItem = synchronizationManager.getDocumentForTest(
"test account",
InstrumentationRegistry.getInstrumentation().context
)

val account = mapItem.toDataClass<Account>()

Assert.assertEquals(account.identifier, "test account")
Assert.assertEquals(account.name, "test name")
}

@After
fun after() {
//delete the created document in test
synchronizationManager.deleteDocument(
"test account"
)
}
}
6 changes: 6 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@

<activity android:name=".ui.online.groups.groupdetails.GroupDetailsActivity" />

<activity android:name=".ui.online.accounting.accounts.accountDetails.AccountDetailsActivity" />

<activity
android:name=".ui.online.accounting.accounts.createaccount.CreateAccountActivity"
android:windowSoftInputMode="adjustResize|stateHidden" />

<activity
android:name=".ui.online.groups.creategroup.CreateGroupActivity"
android:windowSoftInputMode="adjustResize|stateHidden" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ package org.apache.fineract.couchbase

enum class DocumentType(val value: String) {
GROUP("Group"),
CUSTOMER("customer")
CUSTOMER("customer"),
ACCOUNT("Account")
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.apache.fineract.data.datamanager

import io.reactivex.Completable
import io.reactivex.Observable
import io.reactivex.ObservableSource
import io.reactivex.functions.Function
Expand Down Expand Up @@ -36,6 +37,11 @@ class DataManagerAccounting @Inject constructor(val baseManagerApi: BaseApiManag
.onErrorResumeNext(Function<Throwable, ObservableSource<AccountPage>>
{ Observable.just(FakeRemoteDataSource.getAccountPage()) })

fun createAccount(account: Account) : Completable =
baseManagerApi.accountingService.createAccount(account)

fun updateAccount(identifier: String, account: Account) : Completable =
baseManagerApi.accountingService.updateAccount(identifier, account)

fun findAccount(identifier: String): Observable<Account> =
baseManagerApi.accountingService.findAccount(identifier)
Expand Down
Loading