I'm trying to test a spinner that should display while loading the information from an API. The problem is that I can't assert the initial state VISIBLE because it disappear too fast when the results are emitted back thus always having a failing test
Expected: (view has effective visibility <VISIBLE> and view.getGlobalVisibleRect() to return non-empty rectangle)
Got: view.getVisibility() was <GONE>
The first attempt using ui-automator
@Test
fun displayLoaderWhileFetchingPlaylistDetails() {
IdlingRegistry.getInstance().unregister(idlingResource)
uiObjectWithId(R.id.playlist_list).getChild(UiSelector().clickable(true).index(0)).click()
val spinner = uiObjectWithId(R.id.playlist_details_loader)
assertTrue(spinner.exists())
}
Another variant for the test without ui-automator
@Test
fun displayLoaderWhileFetchingPlaylistDetails2() {
IdlingRegistry.getInstance().unregister(idlingResource)
onView(
allOf(
withId(R.id.playlist_image),
isDescendantOfA(withPositionInParent(R.id.playlist_list, 0))
)
)
.perform(click())
assertDisplayed(R.id.playlist_details_loader)
}
ui-automator helper
fun uiObjectWithId(@IdRes id: Int): UiObject {
val resourceId = getTargetContext().resources.getResourceName(id);
val selector = UiSelector().resourceId(resourceId)
return UiDevice.getInstance(getInstrumentation()).findObject(selector)
}
Fragment
private fun observeLoaderState() {
viewModel.playlistLoader.observe(this as LifecycleOwner) { playlistSpinner ->
when (playlistSpinner) {
true -> playlist_details_loader.visibility = View.VISIBLE
else -> playlist_details_loader.visibility = View.GONE
}
}
}
ViewModel
class PlaylistDetailViewModel(
private val repository: PlaylistRepository
) : ViewModel() {
val playlistLoader = MutableLiveData<Boolean>()
fun getPlaylistDetails(playlistId: String) = liveData {
playlistLoader.postValue(true)
emitSource(
repository.getPlaylistDetailsById(playlistId)
.onEach { playlistLoader.postValue(false) }
.asLiveData()
)
}
}
Thanks!