mirror of
https://github.com/hmalik144/Driver.git
synced 2025-12-10 02:45:20 +00:00
Firebase emulator testing (#9)
- Firebase emulator added - Update to Espresso tests - Updated gradle dependencies for espresso - Updated config.yml - Updated android gradle version
This commit is contained in:
@@ -37,17 +37,43 @@ jobs:
|
|||||||
# The next step will run the unit tests
|
# The next step will run the unit tests
|
||||||
- android/run-tests:
|
- android/run-tests:
|
||||||
test-command: ./gradlew testDriverDebugUnitTest --continue
|
test-command: ./gradlew testDriverDebugUnitTest --continue
|
||||||
|
# Install Firebase tools needed for firebase emulator
|
||||||
# Then start the emulator and run the Instrumentation tests!
|
- run:
|
||||||
# - android/start-emulator-and-run-tests:
|
name: Install firebase tools
|
||||||
# test-command: ./gradlew connectedDebugAndroidTest
|
command: |
|
||||||
# system-image: system-images;android-25;google_apis;x86
|
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
|
# And finally run the release build
|
||||||
# - run:
|
# - run:
|
||||||
# name: Assemble release build
|
# name: Assemble release build
|
||||||
# command: |
|
# command: |
|
||||||
# ./gradlew assembleDriverRelease
|
# ./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
|
# Invoke jobs via workflows
|
||||||
# See: https://circleci.com/docs/2.0/configuration-reference/#workflows
|
# See: https://circleci.com/docs/2.0/configuration-reference/#workflows
|
||||||
|
|||||||
5
.firebaserc
Normal file
5
.firebaserc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"default": "driver-8f4a1"
|
||||||
|
}
|
||||||
|
}
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -13,3 +13,5 @@
|
|||||||
/build
|
/build
|
||||||
/captures
|
/captures
|
||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
|
*.log
|
||||||
|
local
|
||||||
|
|||||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -39,7 +39,7 @@
|
|||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17_PREVIEW" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|||||||
@@ -27,6 +27,20 @@ android {
|
|||||||
versionCode 6
|
versionCode 6
|
||||||
versionName "1.6"
|
versionName "1.6"
|
||||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
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 {
|
signingConfigs {
|
||||||
@@ -94,42 +108,47 @@ dependencies {
|
|||||||
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
|
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
|
||||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
|
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
|
||||||
implementation 'androidx.viewpager:viewpager:1.0.0'
|
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"
|
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"
|
implementation "com.google.android.gms:play-services-auth:20.4.1"
|
||||||
// Google firebase
|
/ * Google firebase */
|
||||||
def firebaseVer = "20.1.0"
|
def firebaseCore = "21.1.1"
|
||||||
implementation "com.google.firebase:firebase-core:$firebaseVer"
|
def firebaseAuth = "20.0.0"
|
||||||
implementation "com.google.firebase:firebase-auth:21.0.0"
|
def firebaseStorage = "20.0.0"
|
||||||
implementation "com.google.firebase:firebase-storage:$firebaseVer"
|
def firebaseDatabase = "19.4.0"
|
||||||
implementation "com.google.firebase:firebase-database:$firebaseVer"
|
implementation "com.google.firebase:firebase-core:$firebaseCore"
|
||||||
// Photoviewer
|
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"
|
implementation "com.github.chrisbanes:PhotoView:2.1.0"
|
||||||
/* Picasso photo loader */
|
/ * Picasso photo loader */
|
||||||
implementation "com.squareup.picasso:picasso:2.71828"
|
implementation "com.squareup.picasso:picasso:2.71828"
|
||||||
/* Gson */
|
/ * Gson */
|
||||||
implementation "com.google.code.gson:gson:2.8.9"
|
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"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.6.1"
|
||||||
|
/ * Circle Image View */
|
||||||
// Circle Image View
|
|
||||||
implementation "com.mikhaellopez:circularimageview:4.2.0"
|
implementation "com.mikhaellopez:circularimageview:4.2.0"
|
||||||
|
/ * Kodein Dependency Injection */
|
||||||
//Kodein Dependency Injection
|
|
||||||
def kodein_version = "6.2.1"
|
def kodein_version = "6.2.1"
|
||||||
implementation "org.kodein.di:kodein-di-generic-jvm:$kodein_version"
|
implementation "org.kodein.di:kodein-di-generic-jvm:$kodein_version"
|
||||||
implementation "org.kodein.di:kodein-di-framework-android-x:$kodein_version"
|
implementation "org.kodein.di:kodein-di-framework-android-x:$kodein_version"
|
||||||
|
/ * Image Carousal */
|
||||||
/* Image Carousal */
|
|
||||||
implementation 'com.synnapps:carouselview:0.1.5'
|
implementation 'com.synnapps:carouselview:0.1.5'
|
||||||
|
|
||||||
/ * Glide */
|
/ * Glide */
|
||||||
implementation 'com.github.bumptech.glide:glide:4.12.0'
|
implementation 'com.github.bumptech.glide:glide:4.12.0'
|
||||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
|
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
|
||||||
|
/ * OKHttp */
|
||||||
|
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ import androidx.test.espresso.Espresso.onData
|
|||||||
import androidx.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import androidx.test.espresso.ViewInteraction
|
import androidx.test.espresso.ViewInteraction
|
||||||
import androidx.test.espresso.action.ViewActions
|
import androidx.test.espresso.action.ViewActions
|
||||||
import androidx.test.espresso.assertion.ViewAssertions
|
|
||||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import androidx.test.espresso.matcher.ViewMatchers
|
import androidx.test.espresso.matcher.ViewMatchers
|
||||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
import org.hamcrest.CoreMatchers.*
|
import org.hamcrest.CoreMatchers.allOf
|
||||||
|
import org.hamcrest.CoreMatchers.anything
|
||||||
|
|
||||||
open class BaseTestRobot {
|
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())
|
onView(withId(resId)).perform(ViewActions.replaceText(text), ViewActions.closeSoftKeyboard())
|
||||||
|
|
||||||
fun clickButton(resId: Int): ViewInteraction = onView((withId(resId))).perform(ViewActions.click())
|
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 textView(resId: Int): ViewInteraction = onView(withId(resId))
|
||||||
|
|
||||||
fun matchText(viewInteraction: ViewInteraction, text: String): ViewInteraction = viewInteraction
|
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)
|
fun matchText(resId: Int, text: String): ViewInteraction = matchText(textView(resId), text)
|
||||||
|
|
||||||
|
|||||||
@@ -1,38 +1,60 @@
|
|||||||
package h_mal.appttude.com
|
package h_mal.appttude.com
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
import androidx.annotation.StringRes
|
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.espresso.IdlingRegistry
|
||||||
import androidx.test.rule.ActivityTestRule
|
import androidx.test.espresso.IdlingResource
|
||||||
import h_mal.appttude.com.espresso.IdlingResourceClass
|
import androidx.test.espresso.UiController
|
||||||
import org.junit.AfterClass
|
import androidx.test.espresso.ViewAction
|
||||||
import org.junit.BeforeClass
|
import androidx.test.espresso.matcher.ViewMatchers.isRoot
|
||||||
import org.junit.Ignore
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import org.junit.Rule
|
import h_mal.appttude.com.base.BaseActivity
|
||||||
|
import org.hamcrest.Matcher
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
|
||||||
abstract class BaseUiTest<T : AppCompatActivity> {
|
|
||||||
|
|
||||||
@Ignore
|
open class BaseUiTest<T : BaseActivity<*>>(
|
||||||
abstract fun getApplicationClass(): Class<T>
|
private val activity: Class<T>
|
||||||
|
) {
|
||||||
|
|
||||||
@get:Rule
|
private lateinit var mActivityScenarioRule: ActivityScenario<T>
|
||||||
var mActivityTestRule = ActivityTestRule(getApplicationClass())
|
private var mIdlingResource: IdlingResource? = null
|
||||||
|
|
||||||
companion object {
|
@Before
|
||||||
@BeforeClass
|
fun setup() {
|
||||||
@JvmStatic
|
beforeLaunch()
|
||||||
fun setUp() {
|
mActivityScenarioRule = ActivityScenario.launch(activity)
|
||||||
IdlingRegistry.getInstance().register(IdlingResourceClass.countingIdlingResource)
|
mActivityScenarioRule.onActivity {
|
||||||
}
|
mIdlingResource = it.getIdlingResource()!!
|
||||||
|
IdlingRegistry.getInstance().register(mIdlingResource)
|
||||||
@AfterClass
|
|
||||||
@JvmStatic
|
|
||||||
fun tearDown() {
|
|
||||||
IdlingRegistry.getInstance().unregister(IdlingResourceClass.countingIdlingResource)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getResourceString(@StringRes stringRes: Int): String {
|
@After
|
||||||
return mActivityTestRule.activity.getString(stringRes)
|
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() {}
|
||||||
}
|
}
|
||||||
9
app/src/androidTest/java/h_mal/appttude/com/Constants.kt
Normal file
9
app/src/androidTest/java/h_mal/appttude/com/Constants.kt
Normal file
@@ -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!"
|
||||||
87
app/src/androidTest/java/h_mal/appttude/com/FirebaseTest.kt
Normal file
87
app/src/androidTest/java/h_mal/appttude/com/FirebaseTest.kt
Normal file
@@ -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<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
|
||||||
|
}
|
||||||
|
}
|
||||||
62
app/src/androidTest/java/h_mal/appttude/com/WebUtils.kt
Normal file
62
app/src/androidTest/java/h_mal/appttude/com/WebUtils.kt
Normal file
@@ -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 <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.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
|
||||||
|
)
|
||||||
@@ -8,10 +8,4 @@ class HomeRobot: BaseTestRobot() {
|
|||||||
|
|
||||||
fun checkTitleExists(title: String) = matchText(R.id.prova_title_tv, title)
|
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)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ import h_mal.appttude.com.R
|
|||||||
fun login(func: LoginRobot.() -> Unit) = LoginRobot().apply { func() }
|
fun login(func: LoginRobot.() -> Unit) = LoginRobot().apply { func() }
|
||||||
class LoginRobot: BaseTestRobot() {
|
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)
|
fun setPassword(pass: String) = fillEditText(R.id.password, pass)
|
||||||
|
|
||||||
@@ -3,40 +3,31 @@ package h_mal.appttude.com.tests
|
|||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.LargeTest
|
import androidx.test.filters.LargeTest
|
||||||
import androidx.test.rule.ActivityTestRule
|
import h_mal.appttude.com.FirebaseTest
|
||||||
import com.google.firebase.auth.FirebaseAuth
|
|
||||||
import h_mal.appttude.com.BaseUiTest
|
|
||||||
import h_mal.appttude.com.R
|
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.home
|
||||||
import h_mal.appttude.com.ui.user.LoginActivity
|
|
||||||
import h_mal.appttude.com.robots.login
|
import h_mal.appttude.com.robots.login
|
||||||
import h_mal.appttude.com.robots.register
|
import h_mal.appttude.com.robots.register
|
||||||
|
import h_mal.appttude.com.ui.user.LoginActivity
|
||||||
import org.junit.*
|
import org.junit.*
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class LoginActivityTest: BaseUiTest<LoginActivity>() {
|
class RegisteredUserAuthenticationActivityTest : FirebaseTest<LoginActivity>(LoginActivity::class.java, registered = true, signedIn = false) {
|
||||||
|
|
||||||
@Ignore
|
|
||||||
override fun getApplicationClass() = LoginActivity::class.java
|
|
||||||
|
|
||||||
@After
|
|
||||||
fun afterTest(){
|
|
||||||
FirebaseAuth.getInstance().signOut()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun verifyUserLogin_validUsernameAndPassword_loggedIn() {
|
fun verifyUserLogin_validUsernameAndPassword_loggedIn() {
|
||||||
login {
|
login {
|
||||||
setEmail("test-user@testuserdriver.com")
|
waitFor(1100)
|
||||||
setPassword("Password1234")
|
setEmail(getEmail())
|
||||||
|
setPassword(USER_PASSWORD)
|
||||||
clickLogin()
|
clickLogin()
|
||||||
}
|
}
|
||||||
home {
|
home {
|
||||||
checkTitleExists(getResourceString(R.string.welcome_title))
|
checkTitleExists(getResourceString(R.string.welcome_title))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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>(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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
7
app/src/debug/AndroidManifest.xml
Normal file
7
app/src/debug/AndroidManifest.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<manifest xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<application android:usesCleartextTraffic="true"
|
||||||
|
tools:ignore="MissingApplicationIcon" />
|
||||||
|
|
||||||
|
</manifest>
|
||||||
6
app/src/debug/res/xml/network_security_config.xml
Normal file
6
app/src/debug/res/xml/network_security_config.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<network-security-config>
|
||||||
|
<domain-config cleartextTrafficPermitted="true">
|
||||||
|
<domain>10.0.2.2</domain>
|
||||||
|
</domain-config>
|
||||||
|
</network-security-config>
|
||||||
@@ -4,10 +4,7 @@ import android.os.Bundle
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import h_mal.appttude.com.R
|
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.utils.navigateTo
|
||||||
import h_mal.appttude.com.viewmodels.DriverLicenseViewModel
|
|
||||||
|
|
||||||
import kotlinx.android.synthetic.main.fragment_driver_overall.*
|
import kotlinx.android.synthetic.main.fragment_driver_overall.*
|
||||||
|
|
||||||
class DriverOverallFragment : Fragment(R.layout.fragment_driver_overall) {
|
class DriverOverallFragment : Fragment(R.layout.fragment_driver_overall) {
|
||||||
|
|||||||
@@ -10,10 +10,8 @@ import h_mal.appttude.com.utils.navigateTo
|
|||||||
import h_mal.appttude.com.utils.show
|
import h_mal.appttude.com.utils.show
|
||||||
import h_mal.appttude.com.viewmodels.RoleViewModel
|
import h_mal.appttude.com.viewmodels.RoleViewModel
|
||||||
import kotlinx.android.synthetic.main.driver_profile_request.*
|
import kotlinx.android.synthetic.main.driver_profile_request.*
|
||||||
|
|
||||||
import kotlinx.android.synthetic.main.fragment_home_driver.*
|
import kotlinx.android.synthetic.main.fragment_home_driver.*
|
||||||
import kotlinx.android.synthetic.main.home_buttons_container.*
|
import kotlinx.android.synthetic.main.home_buttons_container.*
|
||||||
import kotlinx.android.synthetic.main.home_buttons_container.driver
|
|
||||||
|
|
||||||
|
|
||||||
class HomeFragment : DataSubmissionBaseFragment<RoleViewModel, String>(R.layout.fragment_home_driver) {
|
class HomeFragment : DataSubmissionBaseFragment<RoleViewModel, String>(R.layout.fragment_home_driver) {
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ import android.os.Bundle
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import h_mal.appttude.com.R
|
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.utils.navigateTo
|
||||||
import h_mal.appttude.com.viewmodels.DriverLicenseViewModel
|
|
||||||
import kotlinx.android.synthetic.main.fragment_vehicle_overall.*
|
import kotlinx.android.synthetic.main.fragment_vehicle_overall.*
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package h_mal.appttude.com.ui
|
package h_mal.appttude.com.ui
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
import h_mal.appttude.com.R
|
import h_mal.appttude.com.R
|
||||||
import h_mal.appttude.com.utils.navigateTo
|
import h_mal.appttude.com.utils.navigateTo
|
||||||
import kotlinx.android.synthetic.driver.fragment_welcome.*
|
import kotlinx.android.synthetic.driver.fragment_welcome.*
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package h_mal.appttude.com.ui.driverprofile
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import h_mal.appttude.com.dialogs.DateDialog
|
|
||||||
import h_mal.appttude.com.R
|
import h_mal.appttude.com.R
|
||||||
import h_mal.appttude.com.base.DataSubmissionBaseFragment
|
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.model.DriverProfileObject
|
||||||
import h_mal.appttude.com.utils.setGlideImage
|
import h_mal.appttude.com.utils.setGlideImage
|
||||||
import h_mal.appttude.com.viewmodels.DriverProfileViewModel
|
import h_mal.appttude.com.viewmodels.DriverProfileViewModel
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package h_mal.appttude.com.ui.driverprofile
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import h_mal.appttude.com.dialogs.DateDialog
|
|
||||||
import h_mal.appttude.com.R
|
import h_mal.appttude.com.R
|
||||||
import h_mal.appttude.com.base.DataSubmissionBaseFragment
|
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.model.PrivateHireObject
|
||||||
import h_mal.appttude.com.utils.setGlideImage
|
import h_mal.appttude.com.utils.setGlideImage
|
||||||
import h_mal.appttude.com.viewmodels.PrivateHireLicenseViewModel
|
import h_mal.appttude.com.viewmodels.PrivateHireLicenseViewModel
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package h_mal.appttude.com.ui.vehicleprofile
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import h_mal.appttude.com.model.LogbookObject
|
|
||||||
import h_mal.appttude.com.R
|
import h_mal.appttude.com.R
|
||||||
import h_mal.appttude.com.base.DataSubmissionBaseFragment
|
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.utils.setGlideImage
|
||||||
import h_mal.appttude.com.viewmodels.LogbookViewModel
|
import h_mal.appttude.com.viewmodels.LogbookViewModel
|
||||||
import kotlinx.android.synthetic.main.fragment_logbook.*
|
import kotlinx.android.synthetic.main.fragment_logbook.*
|
||||||
|
|||||||
@@ -3,10 +3,9 @@ package h_mal.appttude.com.ui.vehicleprofile
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
|
||||||
import h_mal.appttude.com.dialogs.DateDialog
|
|
||||||
import h_mal.appttude.com.R
|
import h_mal.appttude.com.R
|
||||||
import h_mal.appttude.com.base.DataSubmissionBaseFragment
|
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.model.MotObject
|
||||||
import h_mal.appttude.com.utils.setGlideImage
|
import h_mal.appttude.com.utils.setGlideImage
|
||||||
import h_mal.appttude.com.viewmodels.MotViewModel
|
import h_mal.appttude.com.viewmodels.MotViewModel
|
||||||
|
|||||||
@@ -3,11 +3,10 @@ package h_mal.appttude.com.ui.vehicleprofile
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
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.R
|
||||||
import h_mal.appttude.com.base.DataSubmissionBaseFragment
|
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.utils.setGlideImage
|
||||||
import h_mal.appttude.com.viewmodels.PrivateHireVehicleViewModel
|
import h_mal.appttude.com.viewmodels.PrivateHireVehicleViewModel
|
||||||
import kotlinx.android.synthetic.main.fragment_private_hire_vehicle.*
|
import kotlinx.android.synthetic.main.fragment_private_hire_vehicle.*
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ package h_mal.appttude.com.ui.vehicleprofile
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
|
||||||
import h_mal.appttude.com.dialogs.DateDialog
|
|
||||||
import h_mal.appttude.com.R
|
import h_mal.appttude.com.R
|
||||||
import h_mal.appttude.com.base.DataSubmissionBaseFragment
|
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.model.VehicleProfileObject
|
||||||
import h_mal.appttude.com.viewmodels.VehicleProfileViewModel
|
import h_mal.appttude.com.viewmodels.VehicleProfileViewModel
|
||||||
import kotlinx.android.synthetic.main.fragment_vehicle_setup.*
|
import kotlinx.android.synthetic.main.fragment_vehicle_setup.*
|
||||||
|
|||||||
@@ -6,11 +6,7 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ListView
|
import android.widget.ListView
|
||||||
import androidx.fragment.app.Fragment
|
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.DatabaseReference
|
||||||
import com.google.firebase.database.ValueEventListener
|
|
||||||
|
|
||||||
import h_mal.appttude.com.R
|
import h_mal.appttude.com.R
|
||||||
|
|
||||||
class ArchiveFragment : Fragment() {
|
class ArchiveFragment : Fragment() {
|
||||||
|
|||||||
@@ -1,19 +1,13 @@
|
|||||||
package h_mal.appttude.com.Archive
|
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.FirebaseClass
|
||||||
//import h_mal.appttude.com.Global.ImageSwiperClass
|
//import h_mal.appttude.com.Global.ImageSwiperClass
|
||||||
//import h_mal.appttude.com.Objects.ArchiveObject
|
//import h_mal.appttude.com.Objects.ArchiveObject
|
||||||
import h_mal.appttude.com.model.InsuranceObject
|
import android.content.Context
|
||||||
import h_mal.appttude.com.R
|
import android.view.View
|
||||||
import h_mal.appttude.com.model.VehicleProfileObject
|
import android.view.ViewGroup
|
||||||
|
import android.widget.BaseAdapter
|
||||||
|
import android.widget.TextView
|
||||||
import h_mal.appttude.com.utils.DateUtils.convertDateStringDatePattern
|
import h_mal.appttude.com.utils.DateUtils.convertDateStringDatePattern
|
||||||
import java.text.ParseException
|
import java.text.ParseException
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.app.Application
|
|||||||
import h_mal.appttude.com.data.FirebaseAuthSource
|
import h_mal.appttude.com.data.FirebaseAuthSource
|
||||||
import h_mal.appttude.com.data.FirebaseDatabaseSource
|
import h_mal.appttude.com.data.FirebaseDatabaseSource
|
||||||
import h_mal.appttude.com.data.FirebaseStorageSource
|
import h_mal.appttude.com.data.FirebaseStorageSource
|
||||||
import h_mal.appttude.com.espresso.IdlingResourceClass
|
|
||||||
import org.kodein.di.Kodein
|
import org.kodein.di.Kodein
|
||||||
import org.kodein.di.KodeinAware
|
import org.kodein.di.KodeinAware
|
||||||
import org.kodein.di.android.x.androidXModule
|
import org.kodein.di.android.x.androidXModule
|
||||||
|
|||||||
@@ -4,27 +4,25 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup.LayoutParams
|
import android.view.ViewGroup.LayoutParams
|
||||||
import android.view.ViewGroup.LayoutParams.*
|
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
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.R
|
||||||
|
import h_mal.appttude.com.application.ApplicationViewModelFactory
|
||||||
import h_mal.appttude.com.data.ViewState
|
import h_mal.appttude.com.data.ViewState
|
||||||
import h_mal.appttude.com.espresso.IdlingResourceClass
|
import h_mal.appttude.com.utils.*
|
||||||
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 org.kodein.di.KodeinAware
|
import org.kodein.di.KodeinAware
|
||||||
import org.kodein.di.android.kodein
|
import org.kodein.di.android.kodein
|
||||||
import org.kodein.di.generic.instance
|
import org.kodein.di.generic.instance
|
||||||
|
|
||||||
|
|
||||||
abstract class BaseActivity<V : BaseViewModel> : AppCompatActivity(), KodeinAware {
|
abstract class BaseActivity<V : BaseViewModel> : AppCompatActivity(), KodeinAware {
|
||||||
|
// The Idling Resource which will be null in production.
|
||||||
|
private var mIdlingResource: BasicIdlingResource? = null
|
||||||
private lateinit var loadingView: View
|
private lateinit var loadingView: View
|
||||||
|
|
||||||
abstract fun getViewModel(): V?
|
abstract fun getViewModel(): V?
|
||||||
@@ -32,7 +30,6 @@ abstract class BaseActivity<V : BaseViewModel> : AppCompatActivity(), KodeinAwar
|
|||||||
|
|
||||||
override val kodein by kodein()
|
override val kodein by kodein()
|
||||||
val factory by instance<ApplicationViewModelFactory>()
|
val factory by instance<ApplicationViewModelFactory>()
|
||||||
private val idlingResource by instance<IdlingResourceClass>()
|
|
||||||
|
|
||||||
inline fun <reified VM : ViewModel> createLazyViewModel(): Lazy<VM> = viewModels { factory }
|
inline fun <reified VM : ViewModel> createLazyViewModel(): Lazy<VM> = viewModels { factory }
|
||||||
inline fun <reified VM : ViewModel> createViewModel(): VM =
|
inline fun <reified VM : ViewModel> createViewModel(): VM =
|
||||||
@@ -54,6 +51,7 @@ abstract class BaseActivity<V : BaseViewModel> : AppCompatActivity(), KodeinAwar
|
|||||||
* loading
|
* loading
|
||||||
*/
|
*/
|
||||||
private fun instantiateLoadingView(){
|
private fun instantiateLoadingView(){
|
||||||
|
// loadingView = View.inflate(this, R.layout.progress_layout, null)
|
||||||
loadingView = layoutInflater.inflate(R.layout.progress_layout, null)
|
loadingView = layoutInflater.inflate(R.layout.progress_layout, null)
|
||||||
loadingView.setOnClickListener(null)
|
loadingView.setOnClickListener(null)
|
||||||
addContentView(loadingView, LayoutParams(MATCH_PARENT, MATCH_PARENT))
|
addContentView(loadingView, LayoutParams(MATCH_PARENT, MATCH_PARENT))
|
||||||
@@ -76,7 +74,7 @@ abstract class BaseActivity<V : BaseViewModel> : AppCompatActivity(), KodeinAwar
|
|||||||
open fun onStarted() {
|
open fun onStarted() {
|
||||||
loadingView.fadeIn()
|
loadingView.fadeIn()
|
||||||
loading = true
|
loading = true
|
||||||
IdlingResourceClass.increment()
|
mIdlingResource?.setIdleState(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,7 +83,7 @@ abstract class BaseActivity<V : BaseViewModel> : AppCompatActivity(), KodeinAwar
|
|||||||
open fun onSuccess(data: Any?) {
|
open fun onSuccess(data: Any?) {
|
||||||
loadingView.fadeOut()
|
loadingView.fadeOut()
|
||||||
loading = false
|
loading = false
|
||||||
IdlingResourceClass.decrement()
|
mIdlingResource?.setIdleState(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,17 +93,17 @@ abstract class BaseActivity<V : BaseViewModel> : AppCompatActivity(), KodeinAwar
|
|||||||
error?.let { displayToast(it) }
|
error?.let { displayToast(it) }
|
||||||
loadingView.fadeOut()
|
loadingView.fadeOut()
|
||||||
loading = false
|
loading = false
|
||||||
IdlingResourceClass.decrement()
|
mIdlingResource?.setIdleState(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun configureObserver() {
|
private fun configureObserver() {
|
||||||
getViewModel()?.uiState?.observe(this, Observer {
|
getViewModel()?.uiState?.observe(this) {
|
||||||
when (it) {
|
when (it) {
|
||||||
is ViewState.HasStarted -> onStarted()
|
is ViewState.HasStarted -> onStarted()
|
||||||
is ViewState.HasData<*> -> onSuccess(it.data.getContentIfNotHandled())
|
is ViewState.HasData<*> -> onSuccess(it.data.getContentIfNotHandled())
|
||||||
is ViewState.HasError -> onFailure(it.error.getContentIfNotHandled())
|
is ViewState.HasError -> onFailure(it.error.getContentIfNotHandled())
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun View.fadeIn() = apply {
|
private fun View.fadeIn() = apply {
|
||||||
@@ -123,4 +121,14 @@ abstract class BaseActivity<V : BaseViewModel> : AppCompatActivity(), KodeinAwar
|
|||||||
if (!loading) super.onBackPressed()
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
package h_mal.appttude.com.base
|
package h_mal.appttude.com.base
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import com.google.firebase.database.DatabaseReference
|
import com.google.firebase.database.DatabaseReference
|
||||||
import com.google.firebase.storage.StorageReference
|
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.Coroutines.io
|
||||||
import h_mal.appttude.com.utils.DateUtils.getDateTimeStamp
|
import h_mal.appttude.com.utils.DateUtils.getDateTimeStamp
|
||||||
import h_mal.appttude.com.utils.getDataFromDatabaseRef
|
import h_mal.appttude.com.utils.getDataFromDatabaseRef
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class FirebaseAuthSource: FirebaseAuthentication{
|
|||||||
): Task<Void> {
|
): Task<Void> {
|
||||||
val profileUpdates = UserProfileChangeRequest.Builder().apply {
|
val profileUpdates = UserProfileChangeRequest.Builder().apply {
|
||||||
name?.let { setDisplayName(it) }
|
name?.let { setDisplayName(it) }
|
||||||
profilePic?.let { setPhotoUri(it) }
|
profilePic?.let { photoUri = it }
|
||||||
}.build()
|
}.build()
|
||||||
return getCurrentUser().updateProfile(profileUpdates)
|
return getCurrentUser().updateProfile(profileUpdates)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package h_mal.appttude.com.data
|
|||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import com.google.firebase.auth.FirebaseAuth
|
import com.google.firebase.auth.FirebaseAuth
|
||||||
import com.google.firebase.auth.FirebaseUser
|
|
||||||
|
|
||||||
class FirebaseLiveData(
|
class FirebaseLiveData(
|
||||||
private val firebaseAuth: FirebaseAuth
|
private val firebaseAuth: FirebaseAuth
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package h_mal.appttude.com.data
|
package h_mal.appttude.com.data
|
||||||
|
|
||||||
import com.google.firebase.auth.FirebaseUser
|
import com.google.firebase.auth.FirebaseUser
|
||||||
import h_mal.appttude.com.utils.Event
|
|
||||||
|
|
||||||
sealed class UserAuthState {
|
sealed class UserAuthState {
|
||||||
object LoggedOut : UserAuthState()
|
object LoggedOut : UserAuthState()
|
||||||
|
|||||||
@@ -5,16 +5,13 @@ import android.app.AlertDialog
|
|||||||
import android.app.DatePickerDialog
|
import android.app.DatePickerDialog
|
||||||
import android.app.DatePickerDialog.OnDateSetListener
|
import android.app.DatePickerDialog.OnDateSetListener
|
||||||
import android.icu.util.Calendar
|
import android.icu.util.Calendar
|
||||||
import android.os.Build
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import h_mal.appttude.com.R
|
import h_mal.appttude.com.R
|
||||||
import h_mal.appttude.com.utils.DateUtils
|
import h_mal.appttude.com.utils.DateUtils
|
||||||
|
|
||||||
|
|
||||||
private const val DATE_FORMAT = "dd/MM/yyyy"
|
private const val DATE_FORMAT = "dd/MM/yyyy"
|
||||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
@Suppress("DEPRECATION")
|
||||||
class DateDialog(
|
class DateDialog(
|
||||||
private val editText: EditText,
|
private val editText: EditText,
|
||||||
dateSelected:(String?) -> Unit
|
dateSelected:(String?) -> Unit
|
||||||
|
|||||||
@@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
3
app/src/main/java/h_mal/appttude/com/ui/.idea/.gitignore
generated
vendored
Normal file
3
app/src/main/java/h_mal/appttude/com/ui/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
@@ -5,9 +5,9 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.google.firebase.auth.AuthResult
|
import com.google.firebase.auth.AuthResult
|
||||||
import com.google.firebase.auth.FirebaseUser
|
import com.google.firebase.auth.FirebaseUser
|
||||||
import h_mal.appttude.com.ui.MainActivity
|
|
||||||
import h_mal.appttude.com.R
|
import h_mal.appttude.com.R
|
||||||
import h_mal.appttude.com.base.BaseActivity
|
import h_mal.appttude.com.base.BaseActivity
|
||||||
|
import h_mal.appttude.com.ui.MainActivity
|
||||||
import h_mal.appttude.com.viewmodels.UserViewModel
|
import h_mal.appttude.com.viewmodels.UserViewModel
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,7 @@ package h_mal.appttude.com.utils
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager.PERMISSION_GRANTED
|
||||||
import android.content.pm.PackageManager.*
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package h_mal.appttude.com.utils
|
package h_mal.appttude.com.utils
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@@ -20,13 +21,9 @@ import androidx.annotation.DrawableRes
|
|||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.bumptech.glide.Glide
|
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.Picasso
|
||||||
import com.squareup.picasso.Target
|
import com.squareup.picasso.Target
|
||||||
import h_mal.appttude.com.R
|
import h_mal.appttude.com.R
|
||||||
import com.bumptech.glide.request.target.Target as GlideRequestTarget
|
|
||||||
|
|
||||||
fun View.show() {
|
fun View.show() {
|
||||||
this.visibility = View.VISIBLE
|
this.visibility = View.VISIBLE
|
||||||
@@ -54,6 +51,7 @@ fun EditText.setEnterPressedListener(action: () -> Unit) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
fun ImageView.setGlideImage(
|
fun ImageView.setGlideImage(
|
||||||
url: String?,
|
url: String?,
|
||||||
@DrawableRes placeholderRes: Int = R.drawable.choice_img_round
|
@DrawableRes placeholderRes: Int = R.drawable.choice_img_round
|
||||||
@@ -70,6 +68,7 @@ fun ImageView.setGlideImage(
|
|||||||
.into(this)
|
.into(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
fun ImageView.setGlideImage(
|
fun ImageView.setGlideImage(
|
||||||
url: Uri?,
|
url: Uri?,
|
||||||
@DrawableRes placeholderRes: Int = R.drawable.choice_img_round
|
@DrawableRes placeholderRes: Int = R.drawable.choice_img_round
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package h_mal.appttude.com.viewmodels
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.google.firebase.database.DatabaseReference
|
import com.google.firebase.database.DatabaseReference
|
||||||
import com.google.firebase.storage.StorageReference
|
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.base.DataSubmissionBaseViewModel
|
||||||
import h_mal.appttude.com.data.FirebaseAuthentication
|
import h_mal.appttude.com.data.FirebaseAuthentication
|
||||||
import h_mal.appttude.com.data.FirebaseDatabaseSource
|
import h_mal.appttude.com.data.FirebaseDatabaseSource
|
||||||
import h_mal.appttude.com.data.FirebaseStorageSource
|
import h_mal.appttude.com.data.FirebaseStorageSource
|
||||||
|
import h_mal.appttude.com.model.InsuranceObject
|
||||||
import h_mal.appttude.com.utils.Coroutines.io
|
import h_mal.appttude.com.utils.Coroutines.io
|
||||||
|
|
||||||
class InsuranceViewModel (
|
class InsuranceViewModel (
|
||||||
@@ -17,7 +17,7 @@ class InsuranceViewModel (
|
|||||||
) : DataSubmissionBaseViewModel<InsuranceObject>(auth, database, storage) {
|
) : DataSubmissionBaseViewModel<InsuranceObject>(auth, database, storage) {
|
||||||
|
|
||||||
override val databaseRef: DatabaseReference = database.getInsuranceDetailsRef(uid)
|
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 val objectName: String = "insurance"
|
||||||
|
|
||||||
override fun getDataFromDatabase() = getDataClass<InsuranceObject>()
|
override fun getDataFromDatabase() = getDataClass<InsuranceObject>()
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package h_mal.appttude.com.viewmodels
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.google.firebase.database.DatabaseReference
|
import com.google.firebase.database.DatabaseReference
|
||||||
import com.google.firebase.storage.StorageReference
|
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.base.DataSubmissionBaseViewModel
|
||||||
import h_mal.appttude.com.data.FirebaseAuthentication
|
import h_mal.appttude.com.data.FirebaseAuthentication
|
||||||
import h_mal.appttude.com.data.FirebaseDatabaseSource
|
import h_mal.appttude.com.data.FirebaseDatabaseSource
|
||||||
import h_mal.appttude.com.data.FirebaseStorageSource
|
import h_mal.appttude.com.data.FirebaseStorageSource
|
||||||
|
import h_mal.appttude.com.model.LogbookObject
|
||||||
import h_mal.appttude.com.utils.Coroutines.io
|
import h_mal.appttude.com.utils.Coroutines.io
|
||||||
|
|
||||||
class LogbookViewModel (
|
class LogbookViewModel (
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package h_mal.appttude.com.viewmodels
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.google.firebase.database.DatabaseReference
|
import com.google.firebase.database.DatabaseReference
|
||||||
import com.google.firebase.storage.StorageReference
|
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.base.DataSubmissionBaseViewModel
|
||||||
import h_mal.appttude.com.data.FirebaseAuthentication
|
import h_mal.appttude.com.data.FirebaseAuthentication
|
||||||
import h_mal.appttude.com.data.FirebaseDatabaseSource
|
import h_mal.appttude.com.data.FirebaseDatabaseSource
|
||||||
import h_mal.appttude.com.data.FirebaseStorageSource
|
import h_mal.appttude.com.data.FirebaseStorageSource
|
||||||
|
import h_mal.appttude.com.model.PrivateHireVehicleObject
|
||||||
import h_mal.appttude.com.utils.Coroutines.io
|
import h_mal.appttude.com.utils.Coroutines.io
|
||||||
|
|
||||||
class PrivateHireVehicleViewModel (
|
class PrivateHireVehicleViewModel (
|
||||||
@@ -17,7 +17,7 @@ class PrivateHireVehicleViewModel (
|
|||||||
) : DataSubmissionBaseViewModel<PrivateHireVehicleObject>(auth, database, storage) {
|
) : DataSubmissionBaseViewModel<PrivateHireVehicleObject>(auth, database, storage) {
|
||||||
|
|
||||||
override val databaseRef: DatabaseReference = database.getPrivateHireVehicleRef(uid)
|
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 val objectName: String = "private hire vehicle license"
|
||||||
|
|
||||||
override fun getDataFromDatabase() = getDataClass<PrivateHireVehicleObject>()
|
override fun getDataFromDatabase() = getDataClass<PrivateHireVehicleObject>()
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import h_mal.appttude.com.data.FirebaseCompletion
|
|||||||
import h_mal.appttude.com.data.FirebaseStorageSource
|
import h_mal.appttude.com.data.FirebaseStorageSource
|
||||||
import h_mal.appttude.com.utils.Coroutines.io
|
import h_mal.appttude.com.utils.Coroutines.io
|
||||||
import kotlinx.coroutines.tasks.await
|
import kotlinx.coroutines.tasks.await
|
||||||
import java.io.IOException
|
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
class UpdateUserViewModel(
|
class UpdateUserViewModel(
|
||||||
private val auth: FirebaseAuthentication,
|
private val auth: FirebaseAuthentication,
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import h_mal.appttude.com.data.FirebaseCompletion
|
|||||||
import h_mal.appttude.com.utils.Coroutines.io
|
import h_mal.appttude.com.utils.Coroutines.io
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.tasks.await
|
import kotlinx.coroutines.tasks.await
|
||||||
import java.io.IOException
|
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
class UserViewModel(
|
class UserViewModel(
|
||||||
val auth: FirebaseAuthentication
|
val auth: FirebaseAuthentication
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
<resources xmlns:android="http://schemas.android.com/apk/res/android"></resources>
|
|
||||||
@@ -9,7 +9,7 @@ buildscript {
|
|||||||
|
|
||||||
}
|
}
|
||||||
dependencies {
|
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 'com.google.gms:google-services:4.3.15'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10"
|
||||||
|
|
||||||
|
|||||||
10
database.rules.json
Normal file
10
database.rules.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"rules": {
|
||||||
|
"user": {
|
||||||
|
".read": true,
|
||||||
|
"$user_id": {
|
||||||
|
".write": "$user_id === auth.uid"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
firebase.json
Normal file
23
firebase.json
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
8
storage.rules
Normal file
8
storage.rules
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
rules_version = '2';
|
||||||
|
service firebase.storage {
|
||||||
|
match /b/{bucket}/o {
|
||||||
|
match /{allPaths=**} {
|
||||||
|
allow read, write: if false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user