From 7f4060f1c240b04d4e00584f5978e843799f5249 Mon Sep 17 00:00:00 2001 From: hmalik144 Date: Fri, 17 Mar 2023 18:37:20 +0000 Subject: [PATCH] Firebase emulator testing (#9) - Firebase emulator added - Update to Espresso tests - Updated gradle dependencies for espresso - Updated config.yml - Updated android gradle version --- .circleci/config.yml | 38 ++++++-- .firebaserc | 5 ++ .gitignore | 2 + .idea/misc.xml | 2 +- app/build.gradle | 67 +++++++++----- .../java/h_mal/appttude/com/BaseTestRobot.kt | 8 +- .../java/h_mal/appttude/com/BaseUiTest.kt | 72 +++++++++------ .../java/h_mal/appttude/com/Constants.kt | 9 ++ .../java/h_mal/appttude/com/FirebaseTest.kt | 87 +++++++++++++++++++ .../java/h_mal/appttude/com/WebUtils.kt | 62 +++++++++++++ .../appttude/com/firebase/SignUpResponse.kt | 10 +++ .../h_mal/appttude/com/robots/HomeRobot.kt | 6 -- .../h_mal/appttude/com/robots/LoginRobot.kt | 2 +- .../appttude/com/robots/RegisterRobot.kt | 0 ...gisteredUserAuthenticationActivityTest.kt} | 23 ++--- .../tests/UserAuthenticationActivityTest.kt | 39 +++++++++ app/src/debug/AndroidManifest.xml | 7 ++ .../debug/res/xml/network_security_config.xml | 6 ++ .../appttude/com/ui/DriverOverallFragment.kt | 3 - .../h_mal/appttude/com/ui/HomeFragment.kt | 2 - .../appttude/com/ui/VehicleOverallFragment.kt | 2 - .../h_mal/appttude/com/ui/WelcomeFragment.kt | 2 +- .../ui/driverprofile/DriverProfileFragment.kt | 2 +- .../PrivateHireLicenseFragment.kt | 2 +- .../com/ui/vehicleprofile/LogbookFragment.kt | 2 +- .../com/ui/vehicleprofile/MotFragment.kt | 3 +- .../PrivateHireVehicleFragment.kt | 5 +- .../vehicleprofile/VehicleProfileFragment.kt | 3 +- .../appttude/com/Archive/ArchiveFragment.kt | 4 - .../com/Archive/ArchiveObjectListAdapter.kt | 16 ++-- .../com/application/DriverApplication.kt | 1 - .../h_mal/appttude/com/base/BaseActivity.kt | 38 ++++---- .../com/base/DataSubmissionBaseViewModel.kt | 6 +- .../appttude/com/data/FirebaseAuthSource.kt | 2 +- .../appttude/com/data/FirebaseLiveData.kt | 1 - .../h_mal/appttude/com/data/UserAuthState.kt | 1 - .../h_mal/appttude/com/dialogs/DateDialog.kt | 5 +- .../com/espresso/IdlingResourceClass.kt | 24 ----- .../h_mal/appttude/com/ui/.idea/.gitignore | 3 + .../appttude/com/ui/user/LoginActivity.kt | 2 +- .../appttude/com/utils/BasicIdlingResource.kt | 32 +++++++ .../appttude/com/utils/PermissionsUtils.kt | 3 +- .../h_mal/appttude/com/utils/ViewUtils.kt | 7 +- .../com/viewmodels/InsuranceViewModel.kt | 4 +- .../com/viewmodels/LogbookViewModel.kt | 2 +- .../viewmodels/PrivateHireVehicleViewModel.kt | 4 +- .../com/viewmodels/UpdateUserViewModel.kt | 2 - .../appttude/com/viewmodels/UserViewModel.kt | 2 - app/src/main/res/values/drawables.xml | 1 - build.gradle | 2 +- database.rules.json | 10 +++ firebase.json | 23 +++++ storage.rules | 8 ++ 53 files changed, 491 insertions(+), 183 deletions(-) create mode 100644 .firebaserc create mode 100644 app/src/androidTest/java/h_mal/appttude/com/Constants.kt create mode 100644 app/src/androidTest/java/h_mal/appttude/com/FirebaseTest.kt create mode 100644 app/src/androidTest/java/h_mal/appttude/com/WebUtils.kt create mode 100644 app/src/androidTest/java/h_mal/appttude/com/firebase/SignUpResponse.kt rename app/src/{androidTest => androidTestDriver}/java/h_mal/appttude/com/robots/HomeRobot.kt (61%) rename app/src/{androidTest => androidTestDriver}/java/h_mal/appttude/com/robots/LoginRobot.kt (90%) rename app/src/{androidTest => androidTestDriver}/java/h_mal/appttude/com/robots/RegisterRobot.kt (100%) rename app/src/{androidTest/java/h_mal/appttude/com/tests/LoginActivityTest.kt => androidTestDriver/java/h_mal/appttude/com/tests/RegisteredUserAuthenticationActivityTest.kt} (59%) create mode 100644 app/src/androidTestDriver/java/h_mal/appttude/com/tests/UserAuthenticationActivityTest.kt create mode 100644 app/src/debug/AndroidManifest.xml create mode 100644 app/src/debug/res/xml/network_security_config.xml delete mode 100644 app/src/main/java/h_mal/appttude/com/espresso/IdlingResourceClass.kt create mode 100644 app/src/main/java/h_mal/appttude/com/ui/.idea/.gitignore create mode 100644 app/src/main/java/h_mal/appttude/com/utils/BasicIdlingResource.kt delete mode 100644 app/src/main/res/values/drawables.xml create mode 100644 database.rules.json create mode 100644 firebase.json create mode 100644 storage.rules diff --git a/.circleci/config.yml b/.circleci/config.yml index a8e3ce4..5833536 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -37,17 +37,43 @@ jobs: # The next step will run the unit tests - android/run-tests: test-command: ./gradlew testDriverDebugUnitTest --continue - -# Then start the emulator and run the Instrumentation tests! -# - android/start-emulator-and-run-tests: -# test-command: ./gradlew connectedDebugAndroidTest -# system-image: system-images;android-25;google_apis;x86 - + # Install Firebase tools needed for firebase emulator + - run: + name: Install firebase tools + command: | + curl -sL firebase.tools | bash + # Then start firebase emulator in the background + - run: + name: Start firebase emulator + command: | + firebase emulators:start + background: true + # Then start the emulator and run the Instrumentation tests! + - android/start-emulator-and-run-tests: + post-emulator-launch-assemble-command: ./gradlew assembleDriverDebugAndroidTest + test-command: ./gradlew connectedDriverDebugAndroidTest + system-image: system-images;android-25;google_apis;x86 # And finally run the release build # - run: # name: Assemble release build # command: | # ./gradlew assembleDriverRelease + # Then publish the artifacts of the Instrumentation tests! + - store_artifacts: + path: app/build/reports/androidTests/connected + destination: reports + # Then publish the artifacts of the Firebase emulator logs! + - run: + name: save firebase emulator logs + command: | + mkdir -p tmp/firebase_logs + cp *.log tmp/firebase_logs + - store_artifacts: + path: tmp/firebase_logs + destination: logs + # Then publish the results of the Instrumentation tests! + - store_test_results: + path: app/build/outputs/androidTest-results/connected # Invoke jobs via workflows # See: https://circleci.com/docs/2.0/configuration-reference/#workflows diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 0000000..dd32fd6 --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "driver-8f4a1" + } +} diff --git a/.gitignore b/.gitignore index 77d1098..0fc0baf 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ /build /captures .externalNativeBuild +*.log +local diff --git a/.idea/misc.xml b/.idea/misc.xml index 1011831..6626cd0 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -39,7 +39,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 22b30ad..f78d18f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -27,6 +27,20 @@ android { versionCode 6 versionName "1.6" testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' + + boolean state = project.rootProject.file('local.properties').canRead() + buildConfigField "boolean", "LocalState", "$state" + } + + android { + sourceSets { + test { + resources.srcDirs += ['src/test/resources'] + } + androidTest { + resources.srcDirs += ['src/androidTest/resources'] + } + } } signingConfigs { @@ -94,42 +108,47 @@ dependencies { implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1" implementation 'androidx.viewpager:viewpager:1.0.0' - testImplementation "junit:junit:4.13.2" - androidTestImplementation "androidx.test.ext:junit:1.1.5" - androidTestImplementation "androidx.test.espresso:espresso-core:3.5.1" - androidTestImplementation "androidx.test:rules:1.5.0" - implementation 'androidx.test.espresso:espresso-idling-resource:3.5.1' - implementation "androidx.legacy:legacy-support-v4:1.0.0" - // Google play services + testImplementation "junit:junit:4.13.2" + / * Android Espresso */ + def testJunitVersion = "1.1.5" + def testRunnerVersion = "1.5.2" + def espressoVersion = "3.5.1" + androidTestImplementation "androidx.test.ext:junit:$testJunitVersion" + androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion" + androidTestImplementation "androidx.test.espresso.idling:idling-concurrent:$espressoVersion" + implementation "androidx.test.espresso:espresso-idling-resource:$espressoVersion" + androidTestImplementation "androidx.test:runner:$testRunnerVersion" + / * Google play services */ implementation "com.google.android.gms:play-services-auth:20.4.1" - // Google firebase - def firebaseVer = "20.1.0" - implementation "com.google.firebase:firebase-core:$firebaseVer" - implementation "com.google.firebase:firebase-auth:21.0.0" - implementation "com.google.firebase:firebase-storage:$firebaseVer" - implementation "com.google.firebase:firebase-database:$firebaseVer" - // Photoviewer + / * Google firebase */ + def firebaseCore = "21.1.1" + def firebaseAuth = "20.0.0" + def firebaseStorage = "20.0.0" + def firebaseDatabase = "19.4.0" + implementation "com.google.firebase:firebase-core:$firebaseCore" + implementation "com.google.firebase:firebase-auth:$firebaseAuth" + implementation "com.google.firebase:firebase-storage:$firebaseStorage" + implementation "com.google.firebase:firebase-database:$firebaseDatabase" + / * Photoviewer */ implementation "com.github.chrisbanes:PhotoView:2.1.0" - /* Picasso photo loader */ + / * Picasso photo loader */ implementation "com.squareup.picasso:picasso:2.71828" - /* Gson */ + / * Gson */ implementation "com.google.code.gson:gson:2.8.9" - /* coroutines support for firebase operations */ + / * coroutines support for firebase operations */ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.6.1" - - // Circle Image View + / * Circle Image View */ implementation "com.mikhaellopez:circularimageview:4.2.0" - - //Kodein Dependency Injection + / * Kodein Dependency Injection */ def kodein_version = "6.2.1" implementation "org.kodein.di:kodein-di-generic-jvm:$kodein_version" implementation "org.kodein.di:kodein-di-framework-android-x:$kodein_version" - - /* Image Carousal */ + / * Image Carousal */ implementation 'com.synnapps:carouselview:0.1.5' - / * Glide */ implementation 'com.github.bumptech.glide:glide:4.12.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' + / * OKHttp */ + implementation 'com.squareup.okhttp3:okhttp:4.10.0' } diff --git a/app/src/androidTest/java/h_mal/appttude/com/BaseTestRobot.kt b/app/src/androidTest/java/h_mal/appttude/com/BaseTestRobot.kt index 8aac1ee..e16ae87 100644 --- a/app/src/androidTest/java/h_mal/appttude/com/BaseTestRobot.kt +++ b/app/src/androidTest/java/h_mal/appttude/com/BaseTestRobot.kt @@ -6,15 +6,15 @@ 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 import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.withId -import org.hamcrest.CoreMatchers.* +import org.hamcrest.CoreMatchers.allOf +import org.hamcrest.CoreMatchers.anything open class BaseTestRobot { - fun fillEditText(resId: Int, text: String): ViewInteraction = + 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()) @@ -22,7 +22,7 @@ open class BaseTestRobot { fun textView(resId: Int): ViewInteraction = onView(withId(resId)) fun matchText(viewInteraction: ViewInteraction, text: String): ViewInteraction = viewInteraction - .check(ViewAssertions.matches(ViewMatchers.withText(text))) + .check(matches(ViewMatchers.withText(text))) fun matchText(resId: Int, text: String): ViewInteraction = matchText(textView(resId), text) diff --git a/app/src/androidTest/java/h_mal/appttude/com/BaseUiTest.kt b/app/src/androidTest/java/h_mal/appttude/com/BaseUiTest.kt index 1added4..b6eb394 100644 --- a/app/src/androidTest/java/h_mal/appttude/com/BaseUiTest.kt +++ b/app/src/androidTest/java/h_mal/appttude/com/BaseUiTest.kt @@ -1,38 +1,60 @@ package h_mal.appttude.com +import android.view.View import androidx.annotation.StringRes -import androidx.appcompat.app.AppCompatActivity +import androidx.test.core.app.ActivityScenario +import androidx.test.espresso.Espresso.onView import androidx.test.espresso.IdlingRegistry -import androidx.test.rule.ActivityTestRule -import h_mal.appttude.com.espresso.IdlingResourceClass -import org.junit.AfterClass -import org.junit.BeforeClass -import org.junit.Ignore -import org.junit.Rule +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.base.BaseActivity +import org.hamcrest.Matcher +import org.junit.After +import org.junit.Before -abstract class BaseUiTest { - @Ignore - abstract fun getApplicationClass(): Class +open class BaseUiTest>( + private val activity: Class +) { - @get:Rule - var mActivityTestRule = ActivityTestRule(getApplicationClass()) + private lateinit var mActivityScenarioRule: ActivityScenario + private var mIdlingResource: IdlingResource? = null - companion object { - @BeforeClass - @JvmStatic - fun setUp() { - IdlingRegistry.getInstance().register(IdlingResourceClass.countingIdlingResource) - } - - @AfterClass - @JvmStatic - fun tearDown() { - IdlingRegistry.getInstance().unregister(IdlingResourceClass.countingIdlingResource) + @Before + fun setup() { + beforeLaunch() + mActivityScenarioRule = ActivityScenario.launch(activity) + mActivityScenarioRule.onActivity { + mIdlingResource = it.getIdlingResource()!! + IdlingRegistry.getInstance().register(mIdlingResource) } } - fun getResourceString(@StringRes stringRes: Int): String { - return mActivityTestRule.activity.getString(stringRes) + @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 = isRoot() + override fun getDescription(): String? = "wait for $delay milliseconds" + override fun perform(uiController: UiController, v: View?) { + uiController.loopMainThreadForAtLeast(delay) + } + }) + } + + open fun beforeLaunch() {} } \ No newline at end of file diff --git a/app/src/androidTest/java/h_mal/appttude/com/Constants.kt b/app/src/androidTest/java/h_mal/appttude/com/Constants.kt new file mode 100644 index 0000000..c450d71 --- /dev/null +++ b/app/src/androidTest/java/h_mal/appttude/com/Constants.kt @@ -0,0 +1,9 @@ +package h_mal.appttude.com + + +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!" \ No newline at end of file diff --git a/app/src/androidTest/java/h_mal/appttude/com/FirebaseTest.kt b/app/src/androidTest/java/h_mal/appttude/com/FirebaseTest.kt new file mode 100644 index 0000000..3204a87 --- /dev/null +++ b/app/src/androidTest/java/h_mal/appttude/com/FirebaseTest.kt @@ -0,0 +1,87 @@ +package h_mal.appttude.com + +import com.google.firebase.auth.FirebaseAuth +import com.google.firebase.database.FirebaseDatabase +import com.google.firebase.storage.FirebaseStorage +import h_mal.appttude.com.base.BaseActivity +import h_mal.appttude.com.data.FirebaseAuthSource +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.tasks.await +import org.junit.After +import org.junit.BeforeClass + +open class FirebaseTest>( + activity: Class, + private val registered: Boolean = false, + private val signedIn: Boolean = false +) : BaseUiTest(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 + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/h_mal/appttude/com/WebUtils.kt b/app/src/androidTest/java/h_mal/appttude/com/WebUtils.kt new file mode 100644 index 0000000..72ce877 --- /dev/null +++ b/app/src/androidTest/java/h_mal/appttude/com/WebUtils.kt @@ -0,0 +1,62 @@ +package h_mal.appttude.com + +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 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 Call.await(): T? { + val objectMapper = Gson() + val typeToken: TypeToken = object : TypeToken() {} + 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 + } + } + } + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/h_mal/appttude/com/firebase/SignUpResponse.kt b/app/src/androidTest/java/h_mal/appttude/com/firebase/SignUpResponse.kt new file mode 100644 index 0000000..1fe472b --- /dev/null +++ b/app/src/androidTest/java/h_mal/appttude/com/firebase/SignUpResponse.kt @@ -0,0 +1,10 @@ +package h_mal.appttude.com.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 +) \ No newline at end of file diff --git a/app/src/androidTest/java/h_mal/appttude/com/robots/HomeRobot.kt b/app/src/androidTestDriver/java/h_mal/appttude/com/robots/HomeRobot.kt similarity index 61% rename from app/src/androidTest/java/h_mal/appttude/com/robots/HomeRobot.kt rename to app/src/androidTestDriver/java/h_mal/appttude/com/robots/HomeRobot.kt index eaf0849..9352c53 100644 --- a/app/src/androidTest/java/h_mal/appttude/com/robots/HomeRobot.kt +++ b/app/src/androidTestDriver/java/h_mal/appttude/com/robots/HomeRobot.kt @@ -8,10 +8,4 @@ class HomeRobot: BaseTestRobot() { fun checkTitleExists(title: String) = matchText(R.id.prova_title_tv, title) - fun clickLogin() = clickButton(R.id.email_sign_in_button) - - fun clickRegister() = clickButton(R.id.register_button) - - fun clickForgotPassword() = clickButton(R.id.forgot) - } \ No newline at end of file diff --git a/app/src/androidTest/java/h_mal/appttude/com/robots/LoginRobot.kt b/app/src/androidTestDriver/java/h_mal/appttude/com/robots/LoginRobot.kt similarity index 90% rename from app/src/androidTest/java/h_mal/appttude/com/robots/LoginRobot.kt rename to app/src/androidTestDriver/java/h_mal/appttude/com/robots/LoginRobot.kt index 56a116d..5eb19bb 100644 --- a/app/src/androidTest/java/h_mal/appttude/com/robots/LoginRobot.kt +++ b/app/src/androidTestDriver/java/h_mal/appttude/com/robots/LoginRobot.kt @@ -7,7 +7,7 @@ import h_mal.appttude.com.R fun login(func: LoginRobot.() -> Unit) = LoginRobot().apply { func() } class LoginRobot: BaseTestRobot() { - fun setEmail(email: String) = fillEditText(R.id.email, email); + fun setEmail(email: String?) = fillEditText(R.id.email, email) fun setPassword(pass: String) = fillEditText(R.id.password, pass) diff --git a/app/src/androidTest/java/h_mal/appttude/com/robots/RegisterRobot.kt b/app/src/androidTestDriver/java/h_mal/appttude/com/robots/RegisterRobot.kt similarity index 100% rename from app/src/androidTest/java/h_mal/appttude/com/robots/RegisterRobot.kt rename to app/src/androidTestDriver/java/h_mal/appttude/com/robots/RegisterRobot.kt diff --git a/app/src/androidTest/java/h_mal/appttude/com/tests/LoginActivityTest.kt b/app/src/androidTestDriver/java/h_mal/appttude/com/tests/RegisteredUserAuthenticationActivityTest.kt similarity index 59% rename from app/src/androidTest/java/h_mal/appttude/com/tests/LoginActivityTest.kt rename to app/src/androidTestDriver/java/h_mal/appttude/com/tests/RegisteredUserAuthenticationActivityTest.kt index e844a93..2133703 100644 --- a/app/src/androidTest/java/h_mal/appttude/com/tests/LoginActivityTest.kt +++ b/app/src/androidTestDriver/java/h_mal/appttude/com/tests/RegisteredUserAuthenticationActivityTest.kt @@ -3,40 +3,31 @@ package h_mal.appttude.com.tests import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest -import androidx.test.rule.ActivityTestRule -import com.google.firebase.auth.FirebaseAuth -import h_mal.appttude.com.BaseUiTest +import h_mal.appttude.com.FirebaseTest import h_mal.appttude.com.R +import h_mal.appttude.com.USER_PASSWORD import h_mal.appttude.com.robots.home -import h_mal.appttude.com.ui.user.LoginActivity import h_mal.appttude.com.robots.login import h_mal.appttude.com.robots.register +import h_mal.appttude.com.ui.user.LoginActivity import org.junit.* import org.junit.runner.RunWith @LargeTest @RunWith(AndroidJUnit4::class) -class LoginActivityTest: BaseUiTest() { - - @Ignore - override fun getApplicationClass() = LoginActivity::class.java - - @After - fun afterTest(){ - FirebaseAuth.getInstance().signOut() - } +class RegisteredUserAuthenticationActivityTest : FirebaseTest(LoginActivity::class.java, registered = true, signedIn = false) { @Test fun verifyUserLogin_validUsernameAndPassword_loggedIn() { login { - setEmail("test-user@testuserdriver.com") - setPassword("Password1234") + waitFor(1100) + setEmail(getEmail()) + setPassword(USER_PASSWORD) clickLogin() } home { checkTitleExists(getResourceString(R.string.welcome_title)) } } - } diff --git a/app/src/androidTestDriver/java/h_mal/appttude/com/tests/UserAuthenticationActivityTest.kt b/app/src/androidTestDriver/java/h_mal/appttude/com/tests/UserAuthenticationActivityTest.kt new file mode 100644 index 0000000..90fe4c7 --- /dev/null +++ b/app/src/androidTestDriver/java/h_mal/appttude/com/tests/UserAuthenticationActivityTest.kt @@ -0,0 +1,39 @@ +package h_mal.appttude.com.tests + + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.LargeTest +import h_mal.appttude.com.FirebaseTest +import h_mal.appttude.com.R +import h_mal.appttude.com.USER_PASSWORD +import h_mal.appttude.com.robots.home +import h_mal.appttude.com.robots.login +import h_mal.appttude.com.robots.register +import h_mal.appttude.com.ui.user.LoginActivity +import org.junit.* +import org.junit.runner.RunWith + + +@LargeTest +@RunWith(AndroidJUnit4::class) +class UserAuthenticationActivityTest : FirebaseTest(LoginActivity::class.java) { + + @Test + fun verifyUserRegistration_validUsernameAndPassword_loggedIn() { + login { + waitFor(1100) + clickRegister() + } + register { + setName("Test User") + setEmail(generateEmailAddress()) + setPassword(USER_PASSWORD) + setPasswordConfirm(USER_PASSWORD) + clickLogin() + } + home { + checkTitleExists(getResourceString(R.string.welcome_title)) + } + } + +} diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..118af13 --- /dev/null +++ b/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/debug/res/xml/network_security_config.xml b/app/src/debug/res/xml/network_security_config.xml new file mode 100644 index 0000000..17abf3a --- /dev/null +++ b/app/src/debug/res/xml/network_security_config.xml @@ -0,0 +1,6 @@ + + + + 10.0.2.2 + + \ No newline at end of file diff --git a/app/src/driver/java/h_mal/appttude/com/ui/DriverOverallFragment.kt b/app/src/driver/java/h_mal/appttude/com/ui/DriverOverallFragment.kt index d7ed21d..fea63be 100644 --- a/app/src/driver/java/h_mal/appttude/com/ui/DriverOverallFragment.kt +++ b/app/src/driver/java/h_mal/appttude/com/ui/DriverOverallFragment.kt @@ -4,10 +4,7 @@ import android.os.Bundle import android.view.View import androidx.fragment.app.Fragment import h_mal.appttude.com.R -import h_mal.appttude.com.base.BaseFragment import h_mal.appttude.com.utils.navigateTo -import h_mal.appttude.com.viewmodels.DriverLicenseViewModel - import kotlinx.android.synthetic.main.fragment_driver_overall.* class DriverOverallFragment : Fragment(R.layout.fragment_driver_overall) { diff --git a/app/src/driver/java/h_mal/appttude/com/ui/HomeFragment.kt b/app/src/driver/java/h_mal/appttude/com/ui/HomeFragment.kt index 09c16ef..8a05ce0 100644 --- a/app/src/driver/java/h_mal/appttude/com/ui/HomeFragment.kt +++ b/app/src/driver/java/h_mal/appttude/com/ui/HomeFragment.kt @@ -10,10 +10,8 @@ import h_mal.appttude.com.utils.navigateTo import h_mal.appttude.com.utils.show import h_mal.appttude.com.viewmodels.RoleViewModel import kotlinx.android.synthetic.main.driver_profile_request.* - import kotlinx.android.synthetic.main.fragment_home_driver.* import kotlinx.android.synthetic.main.home_buttons_container.* -import kotlinx.android.synthetic.main.home_buttons_container.driver class HomeFragment : DataSubmissionBaseFragment(R.layout.fragment_home_driver) { diff --git a/app/src/driver/java/h_mal/appttude/com/ui/VehicleOverallFragment.kt b/app/src/driver/java/h_mal/appttude/com/ui/VehicleOverallFragment.kt index 4b89d48..b870659 100644 --- a/app/src/driver/java/h_mal/appttude/com/ui/VehicleOverallFragment.kt +++ b/app/src/driver/java/h_mal/appttude/com/ui/VehicleOverallFragment.kt @@ -4,9 +4,7 @@ import android.os.Bundle import android.view.View import androidx.fragment.app.Fragment import h_mal.appttude.com.R -import h_mal.appttude.com.base.BaseFragment import h_mal.appttude.com.utils.navigateTo -import h_mal.appttude.com.viewmodels.DriverLicenseViewModel import kotlinx.android.synthetic.main.fragment_vehicle_overall.* diff --git a/app/src/driver/java/h_mal/appttude/com/ui/WelcomeFragment.kt b/app/src/driver/java/h_mal/appttude/com/ui/WelcomeFragment.kt index 5b90f18..a3863a7 100644 --- a/app/src/driver/java/h_mal/appttude/com/ui/WelcomeFragment.kt +++ b/app/src/driver/java/h_mal/appttude/com/ui/WelcomeFragment.kt @@ -1,8 +1,8 @@ package h_mal.appttude.com.ui import android.os.Bundle -import androidx.fragment.app.Fragment import android.view.View +import androidx.fragment.app.Fragment import h_mal.appttude.com.R import h_mal.appttude.com.utils.navigateTo import kotlinx.android.synthetic.driver.fragment_welcome.* diff --git a/app/src/driver/java/h_mal/appttude/com/ui/driverprofile/DriverProfileFragment.kt b/app/src/driver/java/h_mal/appttude/com/ui/driverprofile/DriverProfileFragment.kt index e79655c..8d64174 100644 --- a/app/src/driver/java/h_mal/appttude/com/ui/driverprofile/DriverProfileFragment.kt +++ b/app/src/driver/java/h_mal/appttude/com/ui/driverprofile/DriverProfileFragment.kt @@ -3,9 +3,9 @@ package h_mal.appttude.com.ui.driverprofile import android.net.Uri import android.os.Bundle import android.view.View -import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.R import h_mal.appttude.com.base.DataSubmissionBaseFragment +import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.model.DriverProfileObject import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.viewmodels.DriverProfileViewModel diff --git a/app/src/driver/java/h_mal/appttude/com/ui/driverprofile/PrivateHireLicenseFragment.kt b/app/src/driver/java/h_mal/appttude/com/ui/driverprofile/PrivateHireLicenseFragment.kt index 38bbd90..49c1076 100644 --- a/app/src/driver/java/h_mal/appttude/com/ui/driverprofile/PrivateHireLicenseFragment.kt +++ b/app/src/driver/java/h_mal/appttude/com/ui/driverprofile/PrivateHireLicenseFragment.kt @@ -3,9 +3,9 @@ package h_mal.appttude.com.ui.driverprofile import android.net.Uri import android.os.Bundle import android.view.View -import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.R import h_mal.appttude.com.base.DataSubmissionBaseFragment +import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.model.PrivateHireObject import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.viewmodels.PrivateHireLicenseViewModel diff --git a/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/LogbookFragment.kt b/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/LogbookFragment.kt index de60f40..3d906b9 100644 --- a/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/LogbookFragment.kt +++ b/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/LogbookFragment.kt @@ -3,9 +3,9 @@ package h_mal.appttude.com.ui.vehicleprofile import android.net.Uri import android.os.Bundle import android.view.View -import h_mal.appttude.com.model.LogbookObject import h_mal.appttude.com.R import h_mal.appttude.com.base.DataSubmissionBaseFragment +import h_mal.appttude.com.model.LogbookObject import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.viewmodels.LogbookViewModel import kotlinx.android.synthetic.main.fragment_logbook.* diff --git a/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/MotFragment.kt b/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/MotFragment.kt index 8ffdd9d..a0db309 100644 --- a/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/MotFragment.kt +++ b/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/MotFragment.kt @@ -3,10 +3,9 @@ package h_mal.appttude.com.ui.vehicleprofile import android.net.Uri import android.os.Bundle import android.view.View - -import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.R import h_mal.appttude.com.base.DataSubmissionBaseFragment +import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.model.MotObject import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.viewmodels.MotViewModel diff --git a/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/PrivateHireVehicleFragment.kt b/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/PrivateHireVehicleFragment.kt index 965ea92..5039676 100644 --- a/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/PrivateHireVehicleFragment.kt +++ b/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/PrivateHireVehicleFragment.kt @@ -3,11 +3,10 @@ package h_mal.appttude.com.ui.vehicleprofile import android.net.Uri import android.os.Bundle import android.view.View - -import h_mal.appttude.com.dialogs.DateDialog -import h_mal.appttude.com.model.PrivateHireVehicleObject import h_mal.appttude.com.R import h_mal.appttude.com.base.DataSubmissionBaseFragment +import h_mal.appttude.com.dialogs.DateDialog +import h_mal.appttude.com.model.PrivateHireVehicleObject import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.viewmodels.PrivateHireVehicleViewModel import kotlinx.android.synthetic.main.fragment_private_hire_vehicle.* diff --git a/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/VehicleProfileFragment.kt b/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/VehicleProfileFragment.kt index d8acd1f..c3748fe 100644 --- a/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/VehicleProfileFragment.kt +++ b/app/src/driver/java/h_mal/appttude/com/ui/vehicleprofile/VehicleProfileFragment.kt @@ -2,10 +2,9 @@ package h_mal.appttude.com.ui.vehicleprofile import android.os.Bundle import android.view.View - -import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.R import h_mal.appttude.com.base.DataSubmissionBaseFragment +import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.model.VehicleProfileObject import h_mal.appttude.com.viewmodels.VehicleProfileViewModel import kotlinx.android.synthetic.main.fragment_vehicle_setup.* diff --git a/app/src/main/java/h_mal/appttude/com/Archive/ArchiveFragment.kt b/app/src/main/java/h_mal/appttude/com/Archive/ArchiveFragment.kt index e6e4ee9..af3143a 100644 --- a/app/src/main/java/h_mal/appttude/com/Archive/ArchiveFragment.kt +++ b/app/src/main/java/h_mal/appttude/com/Archive/ArchiveFragment.kt @@ -6,11 +6,7 @@ import android.view.View import android.view.ViewGroup import android.widget.ListView import androidx.fragment.app.Fragment -import com.google.firebase.database.DataSnapshot -import com.google.firebase.database.DatabaseError import com.google.firebase.database.DatabaseReference -import com.google.firebase.database.ValueEventListener - import h_mal.appttude.com.R class ArchiveFragment : Fragment() { diff --git a/app/src/main/java/h_mal/appttude/com/Archive/ArchiveObjectListAdapter.kt b/app/src/main/java/h_mal/appttude/com/Archive/ArchiveObjectListAdapter.kt index 47f15af..acd1e72 100644 --- a/app/src/main/java/h_mal/appttude/com/Archive/ArchiveObjectListAdapter.kt +++ b/app/src/main/java/h_mal/appttude/com/Archive/ArchiveObjectListAdapter.kt @@ -1,19 +1,13 @@ package h_mal.appttude.com.Archive -import android.content.Context -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.BaseAdapter -import android.widget.ImageView -import android.widget.LinearLayout -import android.widget.TextView //import h_mal.appttude.com.Global.FirebaseClass //import h_mal.appttude.com.Global.ImageSwiperClass //import h_mal.appttude.com.Objects.ArchiveObject -import h_mal.appttude.com.model.InsuranceObject -import h_mal.appttude.com.R -import h_mal.appttude.com.model.VehicleProfileObject +import android.content.Context +import android.view.View +import android.view.ViewGroup +import android.widget.BaseAdapter +import android.widget.TextView import h_mal.appttude.com.utils.DateUtils.convertDateStringDatePattern import java.text.ParseException diff --git a/app/src/main/java/h_mal/appttude/com/application/DriverApplication.kt b/app/src/main/java/h_mal/appttude/com/application/DriverApplication.kt index 7a804f1..da47352 100644 --- a/app/src/main/java/h_mal/appttude/com/application/DriverApplication.kt +++ b/app/src/main/java/h_mal/appttude/com/application/DriverApplication.kt @@ -4,7 +4,6 @@ import android.app.Application import h_mal.appttude.com.data.FirebaseAuthSource import h_mal.appttude.com.data.FirebaseDatabaseSource import h_mal.appttude.com.data.FirebaseStorageSource -import h_mal.appttude.com.espresso.IdlingResourceClass import org.kodein.di.Kodein import org.kodein.di.KodeinAware import org.kodein.di.android.x.androidXModule diff --git a/app/src/main/java/h_mal/appttude/com/base/BaseActivity.kt b/app/src/main/java/h_mal/appttude/com/base/BaseActivity.kt index 476613f..94305cd 100644 --- a/app/src/main/java/h_mal/appttude/com/base/BaseActivity.kt +++ b/app/src/main/java/h_mal/appttude/com/base/BaseActivity.kt @@ -4,27 +4,25 @@ import android.content.Intent import android.os.Bundle import android.view.View import android.view.ViewGroup.LayoutParams -import android.view.ViewGroup.LayoutParams.* +import android.view.ViewGroup.LayoutParams.MATCH_PARENT import androidx.activity.viewModels +import androidx.annotation.VisibleForTesting import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.Observer import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider -import h_mal.appttude.com.application.ApplicationViewModelFactory +import androidx.test.espresso.IdlingResource import h_mal.appttude.com.R +import h_mal.appttude.com.application.ApplicationViewModelFactory import h_mal.appttude.com.data.ViewState -import h_mal.appttude.com.espresso.IdlingResourceClass -import h_mal.appttude.com.utils.displayToast -import h_mal.appttude.com.utils.hide -import h_mal.appttude.com.utils.show -import h_mal.appttude.com.utils.triggerAnimation +import h_mal.appttude.com.utils.* import org.kodein.di.KodeinAware import org.kodein.di.android.kodein import org.kodein.di.generic.instance abstract class BaseActivity : AppCompatActivity(), KodeinAware { - + // The Idling Resource which will be null in production. + private var mIdlingResource: BasicIdlingResource? = null private lateinit var loadingView: View abstract fun getViewModel(): V? @@ -32,7 +30,6 @@ abstract class BaseActivity : AppCompatActivity(), KodeinAwar override val kodein by kodein() val factory by instance() - private val idlingResource by instance() inline fun createLazyViewModel(): Lazy = viewModels { factory } inline fun createViewModel(): VM = @@ -54,6 +51,7 @@ abstract class BaseActivity : AppCompatActivity(), KodeinAwar * loading */ private fun instantiateLoadingView(){ +// loadingView = View.inflate(this, R.layout.progress_layout, null) loadingView = layoutInflater.inflate(R.layout.progress_layout, null) loadingView.setOnClickListener(null) addContentView(loadingView, LayoutParams(MATCH_PARENT, MATCH_PARENT)) @@ -76,7 +74,7 @@ abstract class BaseActivity : AppCompatActivity(), KodeinAwar open fun onStarted() { loadingView.fadeIn() loading = true - IdlingResourceClass.increment() + mIdlingResource?.setIdleState(false) } /** @@ -85,7 +83,7 @@ abstract class BaseActivity : AppCompatActivity(), KodeinAwar open fun onSuccess(data: Any?) { loadingView.fadeOut() loading = false - IdlingResourceClass.decrement() + mIdlingResource?.setIdleState(true) } /** @@ -95,17 +93,17 @@ abstract class BaseActivity : AppCompatActivity(), KodeinAwar error?.let { displayToast(it) } loadingView.fadeOut() loading = false - IdlingResourceClass.decrement() + mIdlingResource?.setIdleState(true) } private fun configureObserver() { - getViewModel()?.uiState?.observe(this, Observer { + getViewModel()?.uiState?.observe(this) { when (it) { is ViewState.HasStarted -> onStarted() is ViewState.HasData<*> -> onSuccess(it.data.getContentIfNotHandled()) is ViewState.HasError -> onFailure(it.error.getContentIfNotHandled()) } - }) + } } private fun View.fadeIn() = apply { @@ -123,4 +121,14 @@ abstract class BaseActivity : AppCompatActivity(), KodeinAwar if (!loading) super.onBackPressed() } + /** + * Only called from test, creates and returns a new [BasicIdlingResource]. + */ + @VisibleForTesting + fun getIdlingResource(): IdlingResource? { + if (mIdlingResource == null) { + mIdlingResource = BasicIdlingResource() + } + return mIdlingResource + } } \ No newline at end of file diff --git a/app/src/main/java/h_mal/appttude/com/base/DataSubmissionBaseViewModel.kt b/app/src/main/java/h_mal/appttude/com/base/DataSubmissionBaseViewModel.kt index b4ee8ec..f05af76 100644 --- a/app/src/main/java/h_mal/appttude/com/base/DataSubmissionBaseViewModel.kt +++ b/app/src/main/java/h_mal/appttude/com/base/DataSubmissionBaseViewModel.kt @@ -1,10 +1,12 @@ package h_mal.appttude.com.base import android.net.Uri -import androidx.lifecycle.MutableLiveData import com.google.firebase.database.DatabaseReference import com.google.firebase.storage.StorageReference -import h_mal.appttude.com.data.* +import h_mal.appttude.com.data.FirebaseAuthentication +import h_mal.appttude.com.data.FirebaseCompletion +import h_mal.appttude.com.data.FirebaseDatabaseSource +import h_mal.appttude.com.data.FirebaseStorageSource import h_mal.appttude.com.utils.Coroutines.io import h_mal.appttude.com.utils.DateUtils.getDateTimeStamp import h_mal.appttude.com.utils.getDataFromDatabaseRef diff --git a/app/src/main/java/h_mal/appttude/com/data/FirebaseAuthSource.kt b/app/src/main/java/h_mal/appttude/com/data/FirebaseAuthSource.kt index 143cd58..6cd0682 100644 --- a/app/src/main/java/h_mal/appttude/com/data/FirebaseAuthSource.kt +++ b/app/src/main/java/h_mal/appttude/com/data/FirebaseAuthSource.kt @@ -28,7 +28,7 @@ class FirebaseAuthSource: FirebaseAuthentication{ ): Task { val profileUpdates = UserProfileChangeRequest.Builder().apply { name?.let { setDisplayName(it) } - profilePic?.let { setPhotoUri(it) } + profilePic?.let { photoUri = it } }.build() return getCurrentUser().updateProfile(profileUpdates) } diff --git a/app/src/main/java/h_mal/appttude/com/data/FirebaseLiveData.kt b/app/src/main/java/h_mal/appttude/com/data/FirebaseLiveData.kt index 489267c..48962bb 100644 --- a/app/src/main/java/h_mal/appttude/com/data/FirebaseLiveData.kt +++ b/app/src/main/java/h_mal/appttude/com/data/FirebaseLiveData.kt @@ -2,7 +2,6 @@ package h_mal.appttude.com.data import androidx.lifecycle.LiveData import com.google.firebase.auth.FirebaseAuth -import com.google.firebase.auth.FirebaseUser class FirebaseLiveData( private val firebaseAuth: FirebaseAuth diff --git a/app/src/main/java/h_mal/appttude/com/data/UserAuthState.kt b/app/src/main/java/h_mal/appttude/com/data/UserAuthState.kt index 433ae62..41a9b6b 100644 --- a/app/src/main/java/h_mal/appttude/com/data/UserAuthState.kt +++ b/app/src/main/java/h_mal/appttude/com/data/UserAuthState.kt @@ -1,7 +1,6 @@ package h_mal.appttude.com.data import com.google.firebase.auth.FirebaseUser -import h_mal.appttude.com.utils.Event sealed class UserAuthState { object LoggedOut : UserAuthState() diff --git a/app/src/main/java/h_mal/appttude/com/dialogs/DateDialog.kt b/app/src/main/java/h_mal/appttude/com/dialogs/DateDialog.kt index 3abba2c..f938000 100644 --- a/app/src/main/java/h_mal/appttude/com/dialogs/DateDialog.kt +++ b/app/src/main/java/h_mal/appttude/com/dialogs/DateDialog.kt @@ -5,16 +5,13 @@ import android.app.AlertDialog import android.app.DatePickerDialog import android.app.DatePickerDialog.OnDateSetListener import android.icu.util.Calendar -import android.os.Build -import android.view.View import android.widget.EditText -import androidx.annotation.RequiresApi import h_mal.appttude.com.R import h_mal.appttude.com.utils.DateUtils private const val DATE_FORMAT = "dd/MM/yyyy" -@RequiresApi(api = Build.VERSION_CODES.N) +@Suppress("DEPRECATION") class DateDialog( private val editText: EditText, dateSelected:(String?) -> Unit diff --git a/app/src/main/java/h_mal/appttude/com/espresso/IdlingResourceClass.kt b/app/src/main/java/h_mal/appttude/com/espresso/IdlingResourceClass.kt deleted file mode 100644 index a0166c8..0000000 --- a/app/src/main/java/h_mal/appttude/com/espresso/IdlingResourceClass.kt +++ /dev/null @@ -1,24 +0,0 @@ -package h_mal.appttude.com.espresso - -import androidx.test.espresso.idling.CountingIdlingResource - -object IdlingResourceClass { - private val CLASS_NAME = "IdlingResourceClass" - - private const val RESOURCE = "GLOBAL" - - @JvmField val countingIdlingResource = CountingIdlingResource(RESOURCE) - - fun increment() { - if (!countingIdlingResource.isIdleNow) { - countingIdlingResource.increment() - } - } - - fun decrement() { - if (countingIdlingResource.isIdleNow) { - countingIdlingResource.decrement() - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/h_mal/appttude/com/ui/.idea/.gitignore b/app/src/main/java/h_mal/appttude/com/ui/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/app/src/main/java/h_mal/appttude/com/ui/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/app/src/main/java/h_mal/appttude/com/ui/user/LoginActivity.kt b/app/src/main/java/h_mal/appttude/com/ui/user/LoginActivity.kt index ccd4fd0..c9a1647 100644 --- a/app/src/main/java/h_mal/appttude/com/ui/user/LoginActivity.kt +++ b/app/src/main/java/h_mal/appttude/com/ui/user/LoginActivity.kt @@ -5,9 +5,9 @@ import android.content.Intent import android.os.Bundle import com.google.firebase.auth.AuthResult import com.google.firebase.auth.FirebaseUser -import h_mal.appttude.com.ui.MainActivity import h_mal.appttude.com.R import h_mal.appttude.com.base.BaseActivity +import h_mal.appttude.com.ui.MainActivity import h_mal.appttude.com.viewmodels.UserViewModel diff --git a/app/src/main/java/h_mal/appttude/com/utils/BasicIdlingResource.kt b/app/src/main/java/h_mal/appttude/com/utils/BasicIdlingResource.kt new file mode 100644 index 0000000..c28065f --- /dev/null +++ b/app/src/main/java/h_mal/appttude/com/utils/BasicIdlingResource.kt @@ -0,0 +1,32 @@ +package h_mal.appttude.com.utils + +import androidx.test.espresso.IdlingResource +import androidx.test.espresso.IdlingResource.ResourceCallback +import java.util.concurrent.atomic.AtomicBoolean + +class BasicIdlingResource : IdlingResource { + + private lateinit var mCallback: ResourceCallback + + // Idleness is controlled with this boolean. + private val mIsIdleNow: AtomicBoolean = AtomicBoolean(true) + + override fun getName(): String = this.javaClass.name + + override fun isIdleNow(): Boolean = mIsIdleNow.get() + + override fun registerIdleTransitionCallback(callback: ResourceCallback) { + mCallback = callback + } + + /** + * Sets the new idle state, if isIdleNow is true, it pings the [ResourceCallback]. + * @param isIdleNow false if there are pending operations, true if idle. + */ + fun setIdleState(isIdleNow: Boolean) { + mIsIdleNow.set(isIdleNow) + if (isIdleNow) { + mCallback.onTransitionToIdle() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/h_mal/appttude/com/utils/PermissionsUtils.kt b/app/src/main/java/h_mal/appttude/com/utils/PermissionsUtils.kt index 851976c..71c9a35 100644 --- a/app/src/main/java/h_mal/appttude/com/utils/PermissionsUtils.kt +++ b/app/src/main/java/h_mal/appttude/com/utils/PermissionsUtils.kt @@ -3,8 +3,7 @@ package h_mal.appttude.com.utils import android.app.Activity import android.content.Context import android.content.Intent -import android.content.pm.PackageManager -import android.content.pm.PackageManager.* +import android.content.pm.PackageManager.PERMISSION_GRANTED import android.net.Uri import android.provider.Settings import androidx.appcompat.app.AlertDialog diff --git a/app/src/main/java/h_mal/appttude/com/utils/ViewUtils.kt b/app/src/main/java/h_mal/appttude/com/utils/ViewUtils.kt index 391fd7a..20dc409 100644 --- a/app/src/main/java/h_mal/appttude/com/utils/ViewUtils.kt +++ b/app/src/main/java/h_mal/appttude/com/utils/ViewUtils.kt @@ -1,5 +1,6 @@ package h_mal.appttude.com.utils +import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.content.Intent @@ -20,13 +21,9 @@ import androidx.annotation.DrawableRes import androidx.appcompat.widget.SearchView import androidx.fragment.app.Fragment import com.bumptech.glide.Glide -import com.bumptech.glide.load.DataSource -import com.bumptech.glide.load.engine.GlideException -import com.bumptech.glide.request.RequestListener import com.squareup.picasso.Picasso import com.squareup.picasso.Target import h_mal.appttude.com.R -import com.bumptech.glide.request.target.Target as GlideRequestTarget fun View.show() { this.visibility = View.VISIBLE @@ -54,6 +51,7 @@ fun EditText.setEnterPressedListener(action: () -> Unit) { }) } +@SuppressLint("CheckResult") fun ImageView.setGlideImage( url: String?, @DrawableRes placeholderRes: Int = R.drawable.choice_img_round @@ -70,6 +68,7 @@ fun ImageView.setGlideImage( .into(this) } +@SuppressLint("CheckResult") fun ImageView.setGlideImage( url: Uri?, @DrawableRes placeholderRes: Int = R.drawable.choice_img_round diff --git a/app/src/main/java/h_mal/appttude/com/viewmodels/InsuranceViewModel.kt b/app/src/main/java/h_mal/appttude/com/viewmodels/InsuranceViewModel.kt index 9fb8ee5..2082fb4 100644 --- a/app/src/main/java/h_mal/appttude/com/viewmodels/InsuranceViewModel.kt +++ b/app/src/main/java/h_mal/appttude/com/viewmodels/InsuranceViewModel.kt @@ -3,11 +3,11 @@ package h_mal.appttude.com.viewmodels import android.net.Uri import com.google.firebase.database.DatabaseReference import com.google.firebase.storage.StorageReference -import h_mal.appttude.com.model.InsuranceObject import h_mal.appttude.com.base.DataSubmissionBaseViewModel import h_mal.appttude.com.data.FirebaseAuthentication import h_mal.appttude.com.data.FirebaseDatabaseSource import h_mal.appttude.com.data.FirebaseStorageSource +import h_mal.appttude.com.model.InsuranceObject import h_mal.appttude.com.utils.Coroutines.io class InsuranceViewModel ( @@ -17,7 +17,7 @@ class InsuranceViewModel ( ) : DataSubmissionBaseViewModel(auth, database, storage) { override val databaseRef: DatabaseReference = database.getInsuranceDetailsRef(uid) - override val storageRef: StorageReference? = storage.insuranceStorageRef(uid) + override val storageRef: StorageReference = storage.insuranceStorageRef(uid) override val objectName: String = "insurance" override fun getDataFromDatabase() = getDataClass() diff --git a/app/src/main/java/h_mal/appttude/com/viewmodels/LogbookViewModel.kt b/app/src/main/java/h_mal/appttude/com/viewmodels/LogbookViewModel.kt index aa54cfb..cc1f74c 100644 --- a/app/src/main/java/h_mal/appttude/com/viewmodels/LogbookViewModel.kt +++ b/app/src/main/java/h_mal/appttude/com/viewmodels/LogbookViewModel.kt @@ -3,11 +3,11 @@ package h_mal.appttude.com.viewmodels import android.net.Uri import com.google.firebase.database.DatabaseReference import com.google.firebase.storage.StorageReference -import h_mal.appttude.com.model.LogbookObject import h_mal.appttude.com.base.DataSubmissionBaseViewModel import h_mal.appttude.com.data.FirebaseAuthentication import h_mal.appttude.com.data.FirebaseDatabaseSource import h_mal.appttude.com.data.FirebaseStorageSource +import h_mal.appttude.com.model.LogbookObject import h_mal.appttude.com.utils.Coroutines.io class LogbookViewModel ( diff --git a/app/src/main/java/h_mal/appttude/com/viewmodels/PrivateHireVehicleViewModel.kt b/app/src/main/java/h_mal/appttude/com/viewmodels/PrivateHireVehicleViewModel.kt index 5567e42..335bfcf 100644 --- a/app/src/main/java/h_mal/appttude/com/viewmodels/PrivateHireVehicleViewModel.kt +++ b/app/src/main/java/h_mal/appttude/com/viewmodels/PrivateHireVehicleViewModel.kt @@ -3,11 +3,11 @@ package h_mal.appttude.com.viewmodels import android.net.Uri import com.google.firebase.database.DatabaseReference import com.google.firebase.storage.StorageReference -import h_mal.appttude.com.model.PrivateHireVehicleObject import h_mal.appttude.com.base.DataSubmissionBaseViewModel import h_mal.appttude.com.data.FirebaseAuthentication import h_mal.appttude.com.data.FirebaseDatabaseSource import h_mal.appttude.com.data.FirebaseStorageSource +import h_mal.appttude.com.model.PrivateHireVehicleObject import h_mal.appttude.com.utils.Coroutines.io class PrivateHireVehicleViewModel ( @@ -17,7 +17,7 @@ class PrivateHireVehicleViewModel ( ) : DataSubmissionBaseViewModel(auth, database, storage) { override val databaseRef: DatabaseReference = database.getPrivateHireVehicleRef(uid) - override val storageRef: StorageReference? = storage.privateHireVehicleStorageRef(uid) + override val storageRef: StorageReference = storage.privateHireVehicleStorageRef(uid) override val objectName: String = "private hire vehicle license" override fun getDataFromDatabase() = getDataClass() diff --git a/app/src/main/java/h_mal/appttude/com/viewmodels/UpdateUserViewModel.kt b/app/src/main/java/h_mal/appttude/com/viewmodels/UpdateUserViewModel.kt index 391f644..4787bb9 100644 --- a/app/src/main/java/h_mal/appttude/com/viewmodels/UpdateUserViewModel.kt +++ b/app/src/main/java/h_mal/appttude/com/viewmodels/UpdateUserViewModel.kt @@ -7,8 +7,6 @@ import h_mal.appttude.com.data.FirebaseCompletion import h_mal.appttude.com.data.FirebaseStorageSource import h_mal.appttude.com.utils.Coroutines.io import kotlinx.coroutines.tasks.await -import java.io.IOException -import java.lang.Exception class UpdateUserViewModel( private val auth: FirebaseAuthentication, diff --git a/app/src/main/java/h_mal/appttude/com/viewmodels/UserViewModel.kt b/app/src/main/java/h_mal/appttude/com/viewmodels/UserViewModel.kt index 1818fca..5170ee1 100644 --- a/app/src/main/java/h_mal/appttude/com/viewmodels/UserViewModel.kt +++ b/app/src/main/java/h_mal/appttude/com/viewmodels/UserViewModel.kt @@ -7,8 +7,6 @@ import h_mal.appttude.com.data.FirebaseCompletion import h_mal.appttude.com.utils.Coroutines.io import kotlinx.coroutines.delay import kotlinx.coroutines.tasks.await -import java.io.IOException -import java.lang.Exception class UserViewModel( val auth: FirebaseAuthentication diff --git a/app/src/main/res/values/drawables.xml b/app/src/main/res/values/drawables.xml deleted file mode 100644 index 3505456..0000000 --- a/app/src/main/res/values/drawables.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/build.gradle b/build.gradle index d0d449a..5662f3c 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.1.3' + classpath 'com.android.tools.build:gradle:7.2.2' classpath 'com.google.gms:google-services:4.3.15' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10" diff --git a/database.rules.json b/database.rules.json new file mode 100644 index 0000000..378f192 --- /dev/null +++ b/database.rules.json @@ -0,0 +1,10 @@ +{ + "rules": { + "user": { + ".read": true, + "$user_id": { + ".write": "$user_id === auth.uid" + } + } + } +} \ No newline at end of file diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000..272d4a0 --- /dev/null +++ b/firebase.json @@ -0,0 +1,23 @@ +{ + "emulators": { + "auth": { + "port": 9099 + }, + "database": { + "port": 9000 + }, + "storage": { + "port": 9199 + }, + "ui": { + "enabled": true + }, + "singleProjectMode": true + }, + "database": { + "rules": "database.rules.json" + }, + "storage": { + "rules": "storage.rules" + } +} diff --git a/storage.rules b/storage.rules new file mode 100644 index 0000000..9f33d22 --- /dev/null +++ b/storage.rules @@ -0,0 +1,8 @@ +rules_version = '2'; +service firebase.storage { + match /b/{bucket}/o { + match /{allPaths=**} { + allow read, write: if false; + } + } +}