From 00c57726e36415d2f30bfeca9b95864c64011583 Mon Sep 17 00:00:00 2001 From: hmalik144 Date: Fri, 26 May 2023 13:13:04 +0100 Subject: [PATCH] - Robots added for tests - Tests added - view naming refactoring - Image selecting stubbing added Took 3 hours 48 minutes --- .../com/driver/ui/HomeSuperUserFragment.kt | 1 + .../ui/driverprofile/DriverProfileFragment.kt | 2 +- .../appttude/com/driver/BaseTestRobot.kt | 38 +++++++++++++++---- .../h_mal/appttude/com/driver/FirebaseTest.kt | 20 ++++------ .../driver/firebase/api/FirebaseApiModule.kt | 26 +++++++++++++ .../appttude/com/driver/robots/LoginRobot.kt | 8 ++++ .../com/driver/robots/HomeAdminRobot.kt | 20 ++++++++-- .../appttude/com/driver/tests/UserListTest.kt | 25 ++++++++++++ .../res/layout/fragment_home_driver.xml | 0 .../driver/application/DriverApplication.kt | 13 ------- app/src/main/res/values/strings.xml | 1 + 11 files changed, 117 insertions(+), 37 deletions(-) create mode 100644 app/src/androidTest/java/h_mal/appttude/com/driver/firebase/api/FirebaseApiModule.kt create mode 100644 app/src/androidTestAdmin/java/h_mal/appttude/com/driver/tests/UserListTest.kt rename app/src/{main => driver}/res/layout/fragment_home_driver.xml (100%) diff --git a/app/src/admin/java/h_mal/appttude/com/driver/ui/HomeSuperUserFragment.kt b/app/src/admin/java/h_mal/appttude/com/driver/ui/HomeSuperUserFragment.kt index 4c2787e..f75e34d 100644 --- a/app/src/admin/java/h_mal/appttude/com/driver/ui/HomeSuperUserFragment.kt +++ b/app/src/admin/java/h_mal/appttude/com/driver/ui/HomeSuperUserFragment.kt @@ -131,6 +131,7 @@ class HomeSuperUserFragment : BaseFragment if (count > 6) context.displayToast("Identifier cannot be larger than 6") } diff --git a/app/src/admin/java/h_mal/appttude/com/driver/ui/driverprofile/DriverProfileFragment.kt b/app/src/admin/java/h_mal/appttude/com/driver/ui/driverprofile/DriverProfileFragment.kt index 8a7ec7a..2dc8b81 100644 --- a/app/src/admin/java/h_mal/appttude/com/driver/ui/driverprofile/DriverProfileFragment.kt +++ b/app/src/admin/java/h_mal/appttude/com/driver/ui/driverprofile/DriverProfileFragment.kt @@ -12,7 +12,7 @@ class DriverProfileFragment : override fun setupView(binding: FragmentDriverProfileBinding) { super.setupView(binding) - viewsToHide(binding.submitDriver, binding.addPhoto) + viewsToHide(binding.submit, binding.addPhoto) } override fun setFields(data: DriverProfile) { diff --git a/app/src/androidTest/java/h_mal/appttude/com/driver/BaseTestRobot.kt b/app/src/androidTest/java/h_mal/appttude/com/driver/BaseTestRobot.kt index 4dfdfa0..ed6dcc2 100644 --- a/app/src/androidTest/java/h_mal/appttude/com/driver/BaseTestRobot.kt +++ b/app/src/androidTest/java/h_mal/appttude/com/driver/BaseTestRobot.kt @@ -5,13 +5,17 @@ import android.app.Instrumentation import android.content.Intent import android.content.res.Resources import android.net.Uri +import android.view.View import android.widget.DatePicker import androidx.annotation.StringRes import androidx.recyclerview.widget.RecyclerView.ViewHolder import androidx.test.espresso.Espresso.onData import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.UiController +import androidx.test.espresso.ViewAction import androidx.test.espresso.ViewInteraction import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.swipeDown import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.contrib.PickerActions @@ -20,12 +24,12 @@ import androidx.test.espresso.intent.Intents import androidx.test.espresso.intent.Intents.intending import androidx.test.espresso.intent.matcher.IntentMatchers import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction -import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.* import h_mal.appttude.com.driver.helpers.DataHelper import h_mal.appttude.com.driver.helpers.EspressoHelper.waitForView import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.anything +import org.hamcrest.Matcher import org.hamcrest.Matchers import java.io.File @@ -38,25 +42,25 @@ open class BaseTestRobot { ) fun clickButton(resId: Int): ViewInteraction = - onView((withId(resId))).perform(ViewActions.click()) + onView((withId(resId))).perform(click()) fun matchView(resId: Int): ViewInteraction = onView(withId(resId)) fun matchViewWaitFor(resId: Int): ViewInteraction = waitForView(withId(resId)) fun matchText(viewInteraction: ViewInteraction, text: String): ViewInteraction = viewInteraction - .check(matches(ViewMatchers.withText(text))) + .check(matches(withText(text))) fun matchText(resId: Int, text: String): ViewInteraction = matchText(matchView(resId), text) fun clickListItem(listRes: Int, position: Int) { onData(anything()) .inAdapterView(allOf(withId(listRes))) - .atPosition(position).perform(ViewActions.click()) + .atPosition(position).perform(click()) } - fun clickRecyclerItemWithText(recyclerId: Int, text: String) { - onView(withId(recyclerId)) + fun scrollToRecyclerItem(recyclerId: Int, text: String): ViewInteraction? { + return onView(withId(recyclerId)) .perform( // scrollTo will fail the test if no item matches. RecyclerViewActions.scrollTo( @@ -65,6 +69,26 @@ open class BaseTestRobot { ) } + fun clickViewInRecycler(recyclerId: Int, text: String) { + scrollToRecyclerItem(recyclerId, text)?.perform(click()) + } + + fun clickSubViewInRecycler(recyclerId: Int, text: String, subView: Int) { + scrollToRecyclerItem(recyclerId, text) + ?.perform( + // scrollTo will fail the test if no item matches. + RecyclerViewActions.actionOnItem( + hasDescendant(withText(text)), object : ViewAction { + override fun getDescription(): String = "Matching recycler descendant" + override fun getConstraints(): Matcher? = isRoot() + override fun perform(uiController: UiController?, view: View?) { + view?.findViewById(subView)?.performClick() + } + } + ) + ) + } + fun checkErrorOnTextEntry(resId: Int, errorMessage: String): ViewInteraction = onView(withId(resId)).check(matches(checkErrorMessage(errorMessage))) @@ -78,7 +102,7 @@ open class BaseTestRobot { Resources.getSystem().getString(resId) fun selectDateInPicker(year: Int, month: Int, day: Int) { - onView(ViewMatchers.withClassName(Matchers.equalTo(DatePicker::class.java.name))).perform( + onView(withClassName(Matchers.equalTo(DatePicker::class.java.name))).perform( PickerActions.setDate( year, month, diff --git a/app/src/androidTest/java/h_mal/appttude/com/driver/FirebaseTest.kt b/app/src/androidTest/java/h_mal/appttude/com/driver/FirebaseTest.kt index 6189116..18550f4 100644 --- a/app/src/androidTest/java/h_mal/appttude/com/driver/FirebaseTest.kt +++ b/app/src/androidTest/java/h_mal/appttude/com/driver/FirebaseTest.kt @@ -13,14 +13,10 @@ import org.junit.BeforeClass open class FirebaseTest>( activity: Class, private val registered: Boolean = false, - private val signedIn: Boolean = false + private val signedIn: Boolean = false, + private val signOutAfterTest: Boolean = true ) : BaseUiTest(activity) { - -// @get:Rule -// val intentsRule = IntentsRule() - private val firebaseAuthSource by lazy { FirebaseAuthSource() } - private var email: String? = null companion object { @@ -48,9 +44,10 @@ open class FirebaseTest>( } @After - fun tearDownFirebase() = runBlocking { - removeUser() - firebaseAuthSource.logOut() + fun tearDownFirebase() { + if (signOutAfterTest) { + firebaseAuthSource.logOut() + } } suspend fun setupUser( @@ -85,9 +82,6 @@ open class FirebaseTest>( } fun getEmail(): String? { - firebaseAuthSource.getUser()?.email?.let { - return it - } - return email + return firebaseAuthSource.getUser()?.email ?: email } } \ No newline at end of file diff --git a/app/src/androidTest/java/h_mal/appttude/com/driver/firebase/api/FirebaseApiModule.kt b/app/src/androidTest/java/h_mal/appttude/com/driver/firebase/api/FirebaseApiModule.kt new file mode 100644 index 0000000..6eeb6d7 --- /dev/null +++ b/app/src/androidTest/java/h_mal/appttude/com/driver/firebase/api/FirebaseApiModule.kt @@ -0,0 +1,26 @@ +package h_mal.appttude.com.driver.firebase.api + +import h_mal.appttude.com.driver.firebase.model.SignUpRequest +import h_mal.appttude.com.driver.firebase.model.SignUpResponse +import kotlinx.coroutines.runBlocking + +class FirebaseApiModule { + + private val firebaseApi = FirebaseApi() + + fun signUp(email: String, password: String): SignUpResponse? { + return runBlocking { + val req = SignUpRequest(email = email, password = password) + val response = firebaseApi.signUp(req) + response.body() + } + } + + fun signIn(email: String, password: String): SignUpResponse? { + return runBlocking { + val req = SignUpRequest(email = email, password = password) + val response = firebaseApi.signInWithPassword(req) + response.body() + } + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/h_mal/appttude/com/driver/robots/LoginRobot.kt b/app/src/androidTest/java/h_mal/appttude/com/driver/robots/LoginRobot.kt index c7a76f9..39d005e 100644 --- a/app/src/androidTest/java/h_mal/appttude/com/driver/robots/LoginRobot.kt +++ b/app/src/androidTest/java/h_mal/appttude/com/driver/robots/LoginRobot.kt @@ -1,6 +1,7 @@ package h_mal.appttude.com.driver.robots import h_mal.appttude.com.driver.BaseTestRobot +import h_mal.appttude.com.driver.PASSWORD import h_mal.appttude.com.driver.R @@ -21,4 +22,11 @@ class LoginRobot : BaseTestRobot() { fun checkPasswordError(err: String) = checkErrorOnTextEntry(R.id.password, err) + fun attemptLogin(emailAddress: String, password: String = PASSWORD) { + matchViewWaitFor(R.id.email) + setEmail(emailAddress) + setPassword(password) + clickLogin() + } + } \ No newline at end of file diff --git a/app/src/androidTestAdmin/java/h_mal/appttude/com/driver/robots/HomeAdminRobot.kt b/app/src/androidTestAdmin/java/h_mal/appttude/com/driver/robots/HomeAdminRobot.kt index 7aea1a1..aa749ba 100644 --- a/app/src/androidTestAdmin/java/h_mal/appttude/com/driver/robots/HomeAdminRobot.kt +++ b/app/src/androidTestAdmin/java/h_mal/appttude/com/driver/robots/HomeAdminRobot.kt @@ -1,14 +1,16 @@ package h_mal.appttude.com.driver.robots import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions import androidx.test.espresso.contrib.DrawerActions import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withTagKey import h_mal.appttude.com.driver.BaseTestRobot import h_mal.appttude.com.driver.R import h_mal.appttude.com.driver.base.CustomViewHolder -fun home(func: HomeRobot.() -> Unit) = HomeRobot().apply { func() } -class HomeRobot : BaseTestRobot() { +fun homeAdmin(func: HomeAdminRobot.() -> Unit) = HomeAdminRobot().apply { func() } +class HomeAdminRobot : BaseTestRobot() { fun openDrawer() { onView(withId(R.id.drawer_layout)).perform(DrawerActions.open()) @@ -23,6 +25,18 @@ class HomeRobot : BaseTestRobot() { clickButton(R.id.nav_user_settings) } - fun clickOnItem(text: String) = clickRecyclerItemWithText>(R.id.recycler_view, text) + fun clickOnItem(anyText: String) = + clickViewInRecycler>(R.id.recycler_view, anyText) + fun clickOnDriverIdentifier(anyText: String) = + clickSubViewInRecycler>(R.id.recycler_view, anyText, R.id.driver_no) + + fun submitDialog(text: String) { + onView(withTagKey(R.string.driver_identifier)).perform( + ViewActions.replaceText(text), + ViewActions.closeSoftKeyboard() + ) + // Click OK + onView(withId(android.R.id.button1)).perform(ViewActions.click()) + } } \ No newline at end of file diff --git a/app/src/androidTestAdmin/java/h_mal/appttude/com/driver/tests/UserListTest.kt b/app/src/androidTestAdmin/java/h_mal/appttude/com/driver/tests/UserListTest.kt new file mode 100644 index 0000000..4b5006f --- /dev/null +++ b/app/src/androidTestAdmin/java/h_mal/appttude/com/driver/tests/UserListTest.kt @@ -0,0 +1,25 @@ +package h_mal.appttude.com.driver.tests + +import h_mal.appttude.com.driver.ADMIN_EMAIL +import h_mal.appttude.com.driver.FirebaseTest +import h_mal.appttude.com.driver.robots.homeAdmin +import h_mal.appttude.com.driver.robots.login +import h_mal.appttude.com.driver.ui.user.LoginActivity +import org.junit.Test + +class UserListTest : FirebaseTest(LoginActivity::class.java) { + + @Test + fun loginAsAdmin_updateDriverIdentifier_loggedIn() { + login { + waitFor(1100) + attemptLogin(ADMIN_EMAIL) + } + homeAdmin { + clickOnDriverIdentifier("rsaif660@gmail.com") + submitDialog("ID45") + waitFor(5000) + } + } + +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home_driver.xml b/app/src/driver/res/layout/fragment_home_driver.xml similarity index 100% rename from app/src/main/res/layout/fragment_home_driver.xml rename to app/src/driver/res/layout/fragment_home_driver.xml diff --git a/app/src/main/java/h_mal/appttude/com/driver/application/DriverApplication.kt b/app/src/main/java/h_mal/appttude/com/driver/application/DriverApplication.kt index 844e73e..9800149 100644 --- a/app/src/main/java/h_mal/appttude/com/driver/application/DriverApplication.kt +++ b/app/src/main/java/h_mal/appttude/com/driver/application/DriverApplication.kt @@ -1,9 +1,6 @@ package h_mal.appttude.com.driver.application import android.app.Application -import com.google.firebase.auth.FirebaseAuth -import com.google.firebase.database.FirebaseDatabase -import com.google.firebase.storage.FirebaseStorage import h_mal.appttude.com.driver.data.FirebaseAuthSource import h_mal.appttude.com.driver.data.FirebaseDatabaseSource import h_mal.appttude.com.driver.data.FirebaseStorageSource @@ -18,16 +15,6 @@ import org.kodein.di.generic.singleton class DriverApplication : Application(), KodeinAware { -// override fun onCreate() { -// super.onCreate() -// -// val localHost = "10.0.2.2" -// -// FirebaseAuth.getInstance().useEmulator(localHost, 9099) -// FirebaseDatabase.getInstance().useEmulator(localHost, 9000) -// FirebaseStorage.getInstance().useEmulator(localHost, 9199) -// } - // Kodein aware to initialise the classes used for DI override val kodein = Kodein.lazy { import(androidXModule(this@DriverApplication)) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index abd80bd..de7e047 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -58,6 +58,7 @@ Address of Keeper Postcode of Keeper Start date + driver identifier Vehicle Seized Full name Address