mirror of
https://github.com/hmalik144/Driver.git
synced 2026-03-18 15:36:03 +00:00
- flavours compartmentalised
Took 10 hours 11 minutes
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
package h_mal.appttude.com.driver
|
||||
|
||||
import android.content.res.Resources
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.test.espresso.Espresso.onData
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.ViewInteraction
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.matcher.ViewMatchers
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
import org.hamcrest.CoreMatchers.anything
|
||||
|
||||
open class BaseTestRobot {
|
||||
|
||||
fun fillEditText(resId: Int, text: String?): ViewInteraction =
|
||||
onView(withId(resId)).perform(
|
||||
ViewActions.replaceText(text),
|
||||
ViewActions.closeSoftKeyboard()
|
||||
)
|
||||
|
||||
fun clickButton(resId: Int): ViewInteraction =
|
||||
onView((withId(resId))).perform(ViewActions.click())
|
||||
|
||||
fun textView(resId: Int): ViewInteraction = onView(withId(resId))
|
||||
|
||||
fun matchText(viewInteraction: ViewInteraction, text: String): ViewInteraction = viewInteraction
|
||||
.check(matches(ViewMatchers.withText(text)))
|
||||
|
||||
fun matchText(resId: Int, text: String): ViewInteraction = matchText(textView(resId), text)
|
||||
|
||||
fun clickListItem(listRes: Int, position: Int) {
|
||||
onData(anything())
|
||||
.inAdapterView(allOf(withId(listRes)))
|
||||
.atPosition(position).perform(ViewActions.click())
|
||||
}
|
||||
|
||||
fun checkErrorOnTextEntry(resId: Int, errorMessage: String): ViewInteraction =
|
||||
onView(withId(resId)).check(matches(checkErrorMessage(errorMessage)))
|
||||
|
||||
fun getStringFromResource(@StringRes resId: Int): String =
|
||||
Resources.getSystem().getString(resId)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package h_mal.appttude.com.driver
|
||||
|
||||
import android.view.View
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.IdlingRegistry
|
||||
import androidx.test.espresso.IdlingResource
|
||||
import androidx.test.espresso.UiController
|
||||
import androidx.test.espresso.ViewAction
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isRoot
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import h_mal.appttude.com.driver.base.BaseActivity
|
||||
import org.hamcrest.Matcher
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
|
||||
|
||||
open class BaseUiTest<T : BaseActivity<*,*>>(
|
||||
private val activity: Class<T>
|
||||
) {
|
||||
|
||||
private lateinit var mActivityScenarioRule: ActivityScenario<T>
|
||||
private var mIdlingResource: IdlingResource? = null
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
beforeLaunch()
|
||||
mActivityScenarioRule = ActivityScenario.launch(activity)
|
||||
mActivityScenarioRule.onActivity {
|
||||
mIdlingResource = it.getIdlingResource()!!
|
||||
IdlingRegistry.getInstance().register(mIdlingResource)
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
mIdlingResource?.let {
|
||||
IdlingRegistry.getInstance().unregister(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun getResourceString(@StringRes stringRes: Int): String {
|
||||
return InstrumentationRegistry.getInstrumentation().targetContext.resources.getString(
|
||||
stringRes
|
||||
)
|
||||
}
|
||||
|
||||
fun waitFor(delay: Long) {
|
||||
onView(isRoot()).perform(object : ViewAction {
|
||||
override fun getConstraints(): Matcher<View> = isRoot()
|
||||
override fun getDescription(): String? = "wait for $delay milliseconds"
|
||||
override fun perform(uiController: UiController, v: View?) {
|
||||
uiController.loopMainThreadForAtLeast(delay)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
open fun beforeLaunch() {}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package h_mal.appttude.com.driver
|
||||
|
||||
|
||||
private const val apiKey = "test_key"
|
||||
const val signUpFirebase = "http://identitytoolkit.googleapis.com/v1/accounts:signUp?key=$apiKey"
|
||||
const val deleteAccountFirebase =
|
||||
"http://10.0.2.2:9099/identitytoolkit.googleapis.com/v1/accounts:delete?key=$apiKey"
|
||||
|
||||
|
||||
const val USER_PASSWORD = "LetMeIn123!"
|
||||
@@ -0,0 +1,30 @@
|
||||
package h_mal.appttude.com.driver
|
||||
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import org.hamcrest.Description
|
||||
import org.hamcrest.Matcher
|
||||
import org.hamcrest.TypeSafeMatcher
|
||||
|
||||
|
||||
/**
|
||||
* Matcher for testing error of TextInputLayout
|
||||
*/
|
||||
fun checkErrorMessage(expectedErrorText: String): Matcher<View?>? {
|
||||
return object : TypeSafeMatcher<View?>() {
|
||||
override fun matchesSafely(view: View?): Boolean {
|
||||
if (view is EditText) {
|
||||
return view.error.toString() == expectedErrorText
|
||||
}
|
||||
|
||||
if (view !is TextInputLayout) return false
|
||||
|
||||
val error = view.error ?: return false
|
||||
return expectedErrorText == error.toString()
|
||||
}
|
||||
|
||||
override fun describeTo(d: Description?) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package h_mal.appttude.com.driver
|
||||
|
||||
import com.google.firebase.auth.FirebaseAuth
|
||||
import com.google.firebase.database.FirebaseDatabase
|
||||
import com.google.firebase.storage.FirebaseStorage
|
||||
import h_mal.appttude.com.driver.base.BaseActivity
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthSource
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.tasks.await
|
||||
import org.junit.After
|
||||
import org.junit.BeforeClass
|
||||
|
||||
open class FirebaseTest<T : BaseActivity<*,*>>(
|
||||
activity: Class<T>,
|
||||
private val registered: Boolean = false,
|
||||
private val signedIn: Boolean = false
|
||||
) : BaseUiTest<T>(activity) {
|
||||
|
||||
private val firebaseAuthSource by lazy { FirebaseAuthSource() }
|
||||
|
||||
private var email: String? = null
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Setup firebase emulators before all tests
|
||||
*/
|
||||
@JvmStatic
|
||||
@BeforeClass
|
||||
fun setupFirebase() {
|
||||
val localHost = "10.0.2.2"
|
||||
|
||||
FirebaseAuth.getInstance().useEmulator(localHost, 9099)
|
||||
FirebaseDatabase.getInstance().useEmulator(localHost, 9000)
|
||||
FirebaseStorage.getInstance().useEmulator(localHost, 9199)
|
||||
}
|
||||
}
|
||||
|
||||
override fun beforeLaunch() {
|
||||
if (registered) {
|
||||
runBlocking {
|
||||
setupUser()
|
||||
}
|
||||
if (!signedIn) firebaseAuthSource.logOut()
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDownFirebase() = runBlocking {
|
||||
removeUser()
|
||||
firebaseAuthSource.logOut()
|
||||
}
|
||||
|
||||
suspend fun setupUser(
|
||||
signInEmail: String = generateEmailAddress(),
|
||||
password: String = USER_PASSWORD
|
||||
) {
|
||||
email = signInEmail
|
||||
firebaseAuthSource.registerUser(signInEmail, password).await().user
|
||||
}
|
||||
|
||||
// remove the user we created for testing
|
||||
suspend fun removeUser() {
|
||||
try {
|
||||
getEmail()?.let {
|
||||
if (firebaseAuthSource.getUser() == null) firebaseAuthSource.signIn(
|
||||
email = it,
|
||||
password = USER_PASSWORD
|
||||
).await()
|
||||
firebaseAuthSource.reauthenticate(it, USER_PASSWORD).await()
|
||||
firebaseAuthSource.deleteProfile().await()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun generateEmailAddress(): String {
|
||||
val suffix = (1000..50000).random()
|
||||
email = "test-${suffix}@test-account.com"
|
||||
return email!!
|
||||
}
|
||||
|
||||
fun getEmail(): String? {
|
||||
firebaseAuthSource.getUser()?.email?.let {
|
||||
return it
|
||||
}
|
||||
return email
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package h_mal.appttude.com.driver
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import okhttp3.*
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import java.io.IOException
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.resumeWithException
|
||||
|
||||
class WebUtils {
|
||||
private val okHttpClient by lazy { OkHttpClient() }
|
||||
|
||||
suspend fun <T : Any> post(url: String, body: String): T? {
|
||||
val requestBody = body.toRequestBody()
|
||||
val request = Request.Builder()
|
||||
.post(requestBody)
|
||||
.url(url)
|
||||
.build()
|
||||
|
||||
return okHttpClient.newCall(request).await()
|
||||
}
|
||||
|
||||
suspend fun get(url: String): String? {
|
||||
val request: Request = Request.Builder()
|
||||
.url(url)
|
||||
.build()
|
||||
return okHttpClient.newCall(request).await()
|
||||
}
|
||||
|
||||
private suspend fun <T> Call.await(): T? {
|
||||
val objectMapper = Gson()
|
||||
val typeToken: TypeToken<T> = object : TypeToken<T>() {}
|
||||
return suspendCancellableCoroutine { continuation ->
|
||||
enqueue(object : Callback {
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
continuation.resume(
|
||||
objectMapper.fromJson(
|
||||
response.body?.string(),
|
||||
typeToken.type
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
// Don't bother with resuming the continuation if it is already cancelled.
|
||||
if (continuation.isCancelled) return
|
||||
continuation.resumeWithException(e)
|
||||
}
|
||||
})
|
||||
|
||||
continuation.invokeOnCancellation {
|
||||
try {
|
||||
cancel()
|
||||
} catch (ex: Throwable) {
|
||||
//Ignore cancel exception
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package h_mal.appttude.com.driver.firebase
|
||||
|
||||
data class SignUpResponse(
|
||||
val expiresIn: String? = null,
|
||||
val kind: String? = null,
|
||||
val idToken: String? = null,
|
||||
val localId: String? = null,
|
||||
val email: String? = null,
|
||||
val refreshToken: String? = null
|
||||
)
|
||||
Reference in New Issue
Block a user