Skip to content

Instantly share code, notes, and snippets.

View JoseAlcerreca's full-sized avatar

Jose Alcérreca JoseAlcerreca

View GitHub Profile
/* Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
public class LiveDataTestUtil {
public static <T> T getOrAwaitValue(final LiveData<T> liveData) throws InterruptedException {
final Object[] data = new Object[1];
final CountDownLatch latch = new CountDownLatch(1);
Observer<T> observer = new Observer<T>() {
@Override
public void onChanged(@Nullable T o) {
data[0] = o;
/* Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
fun <T> LiveData<T>.getOrAwaitValue(
time: Long = 2,
timeUnit: TimeUnit = TimeUnit.SECONDS
): T {
var data: T? = null
val latch = CountDownLatch(1)
val observer = object : Observer<T> {
override fun onChanged(o: T?) {
/* Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
@Test
fun isLiveDataEmitting_observeForever() {
viewModel.setNewValue("foo")
// This works but can be improved.
viewModel.liveData2.observeForever { }
// Passes because it's not a result of a Transformation:
/* Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
fun isLiveDataEmitting() {
viewModel.setNewValue("foo")
assertEquals(viewModel.liveData1.value, "foo") // Passes
assertEquals(viewModel.liveData2.value, "FOO") // Fails!
}
/* Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
class MyViewModel : ViewModel() {
private val _liveData1 = MutableLiveData<String>()
val liveData1: LiveData<String> = _liveData1
// [Transformations.map] on liveData1 that converts the value to uppercase:
val liveData2 = _liveData1.map { it.toUpperCase() }
fun setNewValue(newValue: String) {
coroutineScope {
launch { tasksRemoteDataSource.saveTask(it) }
launch { tasksLocalDataSource.saveTask(it) }
}
fun View.showSnackbar(snackbarText: String, timeLength: Int) {
Snackbar.make(this, snackbarText, timeLength).show()
}
object EspressoIdlingResource {
fun increment() { // NO-OP }
fun decrement() { // NO-OP }
}
suspend fun getTask(taskId: String): Result<Task> {
EspressoIdlingResource.increment() // Set app as busy.
// Get off the main thread or suspend
return withContext(ioDispatcher) { …
EspressoIdlingResource.decrement() // Set app as idle.
return@withContext data
}
}
fun View.showSnackbar(snackbarText: String, timeLength: Int) {
Snackbar.make(this, snackbarText, timeLength).run {
addCallback(object: Snackbar.Callback() {
override fun onShown(sb: Snackbar?) {
EspressoIdlingResource.increment()
}
override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
EspressoIdlingResource.decrement()
}