Files
Adeniyi Mayokun 2db76352d8 Release 5(1.0)
* chore: manage dependencies with buildSrc

* chore: setup firebase crashlytics, analytics

* chore: convert build scripts to kotlin dsl

* chore: convert build scripts to kotlin dsl

* chore: remove kotlin android extensions, enable viewbinding

* feat: use bottom sheet in search fragmenrt, format forecast dates

* chore: fix build config issues

* refactor: update .gitignore

* refactor: update .gitignore

* ci: update actions workflow

* refactor: fix failing tests

* chore: fix build config issues

* ci: update actions workflow
2021-07-25 02:07:45 +01:00

97 lines
3.1 KiB
Kotlin

package com.mayokunadeniyi.instantweather.utils
import android.view.View
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.testing.FragmentScenario
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.IdlingResource
import java.util.*
/**
* Created by Mayokun Adeniyi on 25/07/2020.
*/
class DataBindingIdlingResource : IdlingResource {
// List of registered callbacks
private val idlingCallbacks = mutableListOf<IdlingResource.ResourceCallback>()
// Give it a unique id to work around an Espresso bug where you cannot register/unregister
// an idling resource with the same name.
private val id = UUID.randomUUID().toString()
// Holds whether isIdle was called and the result was false. We track this to avoid calling
// onTransitionToIdle callbacks if Espresso never thought we were idle in the first place.
private var wasNotIdle = false
lateinit var activity: FragmentActivity
override fun getName() = "DataBinding $id"
override fun isIdleNow(): Boolean {
val idle = !getBindings().any { it.hasPendingBindings() }
@Suppress("LiftReturnOrAssignment")
if (idle) {
if (wasNotIdle) {
// Notify observers to avoid Espresso race detector.
idlingCallbacks.forEach { it.onTransitionToIdle() }
}
wasNotIdle = false
} else {
wasNotIdle = true
// Check next frame.
activity.findViewById<View>(android.R.id.content).postDelayed(
{
isIdleNow
},
16
)
}
return idle
}
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback) {
idlingCallbacks.add(callback)
}
/**
* Find all binding classes in all currently available fragments.
*/
private fun getBindings(): List<ViewDataBinding> {
val fragments = (activity as? FragmentActivity)
?.supportFragmentManager
?.fragments
val bindings =
fragments?.mapNotNull {
it.view?.getBinding()
} ?: emptyList()
val childrenBindings = fragments?.flatMap { it.childFragmentManager.fragments }
?.mapNotNull { it.view?.getBinding() } ?: emptyList()
return bindings + childrenBindings
}
}
private fun View.getBinding(): ViewDataBinding? = DataBindingUtil.getBinding(this)
/**
* Sets the activity from an [ActivityScenario] to be used from [DataBindingIdlingResource].
*/
fun DataBindingIdlingResource.monitorActivity(
activityScenario: ActivityScenario<out FragmentActivity>
) {
activityScenario.onActivity {
this.activity = it
}
}
/**
* Sets the fragment from a [FragmentScenario] to be used from [DataBindingIdlingResource].
*/
fun DataBindingIdlingResource.monitorFragment(fragmentScenario: FragmentScenario<out Fragment>) {
fragmentScenario.onFragment {
this.activity = it.requireActivity()
}
}