Reputation: 4380
I'm trying to write some tests with the new android-test-kit (Espresso). But I can't find any information on how to check if a dialog is displayed and perform some actions on it (like clicking the positive and negative buttons, e.t.c.). Note that a dialog may be also displayed by a WebView
, not by the application it self.
Any help would be appreciated. I just need a link, or some example code for the basics:
setCancelable(false)
was called on the dialog builder and we want to check that)Thank you in advice!
Upvotes: 102
Views: 75158
Reputation: 7641
If you don't want to check for a specific String in a dialog, you can use hasWindowFocus()
, like this:
// Kotlin, with ActivityScenarioRule
activityScenarioRule.scenario.onActivity { activity ->
val dialogIsDisplayed = !activity.hasWindowFocus()
}
// Kotlin, with ActivityTestRule
val dialogIsDisplayed = !activityTestRule.activity.hasWindowFocus()
// Java 7, with ActivityScenarioRule
activityScenarioRule.getScenario().onActivity(new ActivityScenario.ActivityAction<MyActivity>() {
@Override
public void perform(MyActivity activity) {
boolean dialogIsDisplayed = !activity.hasWindowFocus();
}
});
// Java, with ActivityTestRule
boolean dialogIsDisplayed = !activityTestRule.getActivity().hasWindowFocus();
Sources:
Upvotes: 3
Reputation: 580
Just in case anyone stumbles across this question like I did. All the answers will only work for dialogs WITH dialog buttons. Do not try and use this for progress dialogs without user interaction. Espresso keeps waiting for the app to enter an idle state. As long as the progress dialog is visible the app is not idle.
Upvotes: 4
Reputation: 6910
To verify if dialog appears you can simply check if View with a text that present inside the dialog is shown:
onView(withText("dialogText")).check(matches(isDisplayed()));
or, based on text with id
onView(withId(R.id.myDialogTextId)).check(matches(allOf(withText(myDialogText), isDisplayed()));
To click on dialogs button do this (button1 - OK, button2 - Cancel):
onView(withId(android.R.id.button1)).perform(click());
UPDATE
Upvotes: 144
Reputation: 827
If you have an AlertDialog like that:
You can check if the components are displayed:
int titleId = mActivityTestRule.getActivity().getResources()
.getIdentifier( "alertTitle", "id", "android" );
onView(withId(titleId))
.inRoot(isDialog())
.check(matches(withText(R.string.my_title)))
.check(matches(isDisplayed()));
onView(withId(android.R.id.text1))
.inRoot(isDialog())
.check(matches(withText(R.string.my_message)))
.check(matches(isDisplayed()));
onView(withId(android.R.id.button2))
.inRoot(isDialog())
.check(matches(withText(android.R.string.no)))
.check(matches(isDisplayed()));
onView(withId(android.R.id.button3))
.inRoot(isDialog())
.check(matches(withText(android.R.string.yes)))
.check(matches(isDisplayed()));
and perform an action:
onView(withId(android.R.id.button3)).perform(click());
Upvotes: 30
Reputation: 3285
The button Ids R.id.button1 and R.id.button2 are not going to be same across devices. The Ids may change with the OS versions.
The correct way to achieve this is to use UIAutomator. Include UIAutomator dependency in your build.gradle
// Set this dependency to build and run UI Automator tests
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
and use
// Initialize UiDevice instance
UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
// Search for correct button in the dialog.
UiObject button = uiDevice.findObject(new UiSelector().text("ButtonText"));
if (button.exists() && button.isEnabled()) {
button.click();
}
Upvotes: 3
Reputation: 9450
I currently use this and it seems to work fine.
onView(withText(R.string.my_title))
.inRoot(isDialog()) // <---
.check(matches(isDisplayed()));
Upvotes: 85
Reputation: 4389
To answer question 4, which the accepted answer does not, I modified the following code, which I found here on Stack Overflow (link) for testing whether a Toast was displayed.
@NonNull
public static ViewInteraction getRootView(@NonNull Activity activity, @IdRes int id) {
return onView(withId(id)).inRoot(withDecorView(not(is(activity.getWindow().getDecorView()))));
}
The id
passed in is the id of a View
currently displayed in your dialog. You could also write the method like so:
@NonNull
public static ViewInteraction getRootView(@NonNull Activity activity, @NonNull String text) {
return onView(withText(text)).inRoot(withDecorView(not(is(activity.getWindow().getDecorView()))));
}
And now it's looking for a View
containing a particular text string.
Use it like so:
getRootView(getActivity(), R.id.text_id).perform(click());
Upvotes: 3