Reputation: 23
Eg. I have created two activities and second activities contain recycler item list and progress bar. until finish API call we are waiting for a response and shows progress bar
Upvotes: 2
Views: 1312
Reputation: 1662
This is just an adapted version of jeprubio's solution.
/**
* Wait until the element is accessible and not shown.
* @param millis The maximum timeout to wait for.
*/
fun waitUntilNotShown(millis: Long): ViewAction {
return object : ViewAction {
override fun getConstraints(): Matcher<View> {
return any(View::class.java)
}
override fun getDescription(): String {
return "Wait for a specific view to be hidden, for a max of $millis ms."
}
override fun perform(uiController: UiController, view: View) {
uiController.loopMainThreadUntilIdle()
val startTime = System.currentTimeMillis()
val endTime = startTime + millis
do {
if (!view.isShown) {
return
}
uiController.loopMainThreadForAtLeast(100)
} while (System.currentTimeMillis() < endTime)
throw PerformException.Builder()
.withActionDescription(this.description)
.withViewDescription(HumanReadables.describe(view))
.withCause(TimeoutException())
.build()
}
}
}
Then we can use this way:
onView(withId(R.id.welcome_progress_bar))
.perform(waitUntilNotShown(3_000))
I made this change since I was getting errors when using onView(isRoot())
.
Upvotes: 0
Reputation: 21
//I use this simple code (no IdlingResource os custom matcher). Where viewId is the view you want to verify once ProgressBar is gone
fun viewIsDisplayedAfterProgressDialogIsGone(viewId: Int){
onView(withId(viewId))
.inRoot(not(RootMatchers.isDialog()))
.check(matches(isDisplayed()))
}
Upvotes: 2
Reputation: 18002
So, you want to wait until your ProgressBar is hidden.
You can either create an idling resource
or use a custom ViewAction as this one:
/**
* Perform action of waiting until the element is accessible & not shown.
* @param viewId The id of the view to wait for.
* @param millis The timeout of until when to wait for.
*/
public static ViewAction waitUntilNotShown(final int viewId, final long millis) {
return new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isRoot();
}
@Override
public String getDescription() {
return "wait for a specific view with id <" + viewId + "> is hidden during " + millis + " millis.";
}
@Override
public void perform(final UiController uiController, final View view) {
uiController.loopMainThreadUntilIdle();
final long startTime = System.currentTimeMillis();
final long endTime = startTime + millis;
final Matcher<View> viewMatcher = withId(viewId);
do {
for (View child : TreeIterables.breadthFirstViewTraversal(view)) {
// found view with required ID
if (viewMatcher.matches(child) && !child.isShown()) {
return;
}
}
uiController.loopMainThreadForAtLeast(50);
}
while (System.currentTimeMillis() < endTime);
// timeout happens
throw new PerformException.Builder()
.withActionDescription(this.getDescription())
.withViewDescription(HumanReadables.describe(view))
.withCause(new TimeoutException())
.build();
}
};
}
And you can use it this way:
onView(isRoot()).perform(waitUntilNotShown(R.id.theIdToWaitFor, 5000));
changing theIdToWaitFor
with the specific id of your ProgressBar
and updating the timeout of 5 secs (5000 millis) if necessary.
However, depending on which test you are doing, if this is not an integration test it's better not to make real api calls.
Upvotes: 2