Wait until view become visible with IdleResource
I know this might be too late, but my answer might help someone.
- When you instantiate and register your
AmountViewIdlingResource
, keep a reference to it and only unregister that reference, don't unregister allIdlingResources
. - Your implementation of the
isIdleNow()
method should only call the callback'sonTransitionToIdle()
method if your idling resource is really idle not every time.
I needed to do something similar, to wait for a button to appear on the screen, which in turn only got to be visible after an HTTP call finished. My implementation of a view visibility Idling Resource is as follows:
public class ViewVisibilityIdlingResource implements IdlingResource {
private final View mView;
private final int mExpectedVisibility;
private boolean mIdle;
private ResourceCallback mResourceCallback;
public ViewVisibilityIdlingResource(final View view, final int expectedVisibility) {
this.mView = view;
this.mExpectedVisibility = expectedVisibility;
this.mIdle = false;
this.mResourceCallback = null;
}
@Override
public final String getName() {
return ViewVisibilityIdlingResource.class.getSimpleName();
}
@Override
public final boolean isIdleNow() {
mIdle = mIdle || mView.getVisibility() == mExpectedVisibility;
if (mIdle) {
if (mResourceCallback != null) {
mResourceCallback.onTransitionToIdle();
}
}
return mIdle;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
mResourceCallback = resourceCallback;
}
}
Hope this helps
F1sher
Updated on July 18, 2022Comments
-
F1sher almost 2 years
I am writing Instrumentation tests with usage of Espresso 2.2.
Flow I want to test:
- radioButton clicked by test
- onClick launches request to API
- after every time different time I receive response
- positive response triggers interface method that is called in activity
- onRequestSuccess I am making additional panel on screen named vSetupAmount visible
I want to register IdleResource after click on radioButton so it waits until vSetupAmount becomes visible. But I can't make it work. Please tell me what am I doing wrong.
I have written such IdleResource:
public class AmountViewIdlingResource implements IdlingResource { private CountriesAndRatesActivity activity; private ResourceCallback callback; private SetupAmountView amountView; public AmountViewIdlingResource(CountriesAndRatesActivity activity) { this.activity = activity; amountView = (SetupAmountView) this.activity.findViewById(R.id.vSetupAmount); } @Override public String getName() { return "Amount View idling resource"; } @Override public boolean isIdleNow() { callback.onTransitionToIdle(); return amountView.getVisibility() == View.VISIBLE; } @Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { this.callback = resourceCallback; } }
So I am passing activity to IdleResource, link view with variable. I understand that IdleResource won't let test go through until isIdleNow() returns value true. So if view is View.GONE then it won't go further.
How it looks in test:
// click of radioButton picked from radioGroup onView(withId(rgDeliveries.getChildAt(id).getId())).perform(scrollTo(), click()); // wait for view to become visible Espresso.registerIdlingResources(new AmountViewIdlingResource(getActivity())); // go to button on view onView(withId(R.id.btnGetStarted)).perform(scrollTo()); // unregister idle resource for ( IdlingResource resource : getIdlingResources()) { Espresso.unregisterIdlingResources(resource); }
So I get my click on radioButton. IdleResource is successfully registered but nothing happens. On my device API response comes. vSetupAmount is being displayed but
amountView.getVisibility() == View.VISIBLE;
which is being checked forever (but I see my view on screen) always returns false.
What am I doing wrong?