24

I want to press below button using Espresso, but I'm not sure how. Should I get the resource-id? Or how to set an ID to the AlertDialog??

enter image description here

@RunWith(AndroidJUnit4.class)
public class ApplicationTest {

@Rule
public ActivityTestRule<LoadingActivity> mActivityRule =
        new ActivityTestRule<>(LoadingActivity.class);

@Test
public void loginClickMarker() {
//Doesn't work:
    onView(withText("GA NAAR INSTELLINGEN")).perform(click());
}
}

public class PopupDialog {

public static void showGPSIsDisabled(Context context, String msg, final PopupDialogCallback popupDialogCallback) {
    new AlertDialog.Builder(context)
            .setTitle(context.getString(R.string.location_turned_off))
            .setMessage(msg)
            .setPositiveButton(context.getString(R.string.go_to_settings), new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                    popupDialogCallback.hasClicked();
                }
            }).show();
}
}

android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with text: is "GA NAAR INSTELLINGEN"

piotrek1543
  • 19,130
  • 7
  • 81
  • 94
Jim Clermonts
  • 1,694
  • 8
  • 39
  • 94

6 Answers6

58

According to StackOverflow similar issue: Check if a dialog is displayed with Espresso

You should change your code from:

onView(withText("GA NAAR INSTELLINGEN")).perform(click());

to

onView(withText("GA NAAR INSTELLINGEN")))
    .inRoot(isDialog()) // <---
    .check(matches(isDisplayed()))
    .perform(click());

If it won't work, don't bother to use long with Espresso another great Google's instrumentation test called uiatomator.

Check: http://qathread.blogspot.com/2015/05/espresso-uiautomator-perfect-tandem.html

Example code:

// Initialize UiDevice instance
UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());

// Search for correct button in the dialog.
UiObject button = uiDevice.findObject(new UiSelector().text("GA NAAR INSTELLINGEN"));
if (button.exists() && button.isEnabled()) {
    button.click();
}

Hope it will help

Community
  • 1
  • 1
piotrek1543
  • 19,130
  • 7
  • 81
  • 94
11

Since inRoot(isDialog()) does not seem to work for DialogFragment I use this workaround so far:

enum class AlertDialogButton(@IdRes val resId: Int) {
    POSITIVE(android.R.id.button1),
    NEGATIVE(android.R.id.button2),
    NEUTRAL(android.R.id.button3)
}

fun clickOnButtonInAlertDialog(button: AlertDialogButton) {
    onView(withId(button.resId)).perform(click())
}
JoachimR
  • 5,150
  • 7
  • 45
  • 50
  • Thank you! isDialog() wasn't working for me, but I was able to find button1 and button2. Thank you for explicitly writing out how the different buttons line up with their ID numbers. – Zeek Aran Feb 22 '18 at 16:17
7

For an AlertDialog, the id assigned for each button is:

  • POSITIVE: android.R.id.button1
  • NEGATIVE: android.R.id.button2
  • NEUTRAL: android.R.id.button3

You can check yourself in the AlertController class, setupButtons() method. So you can perform a click as follows:

onView(withId(android.R.id.button1)).perform(click());

giroxiii
  • 655
  • 5
  • 14
6

You might need to close the softkeyboard like this:

        onView(withId(R.id.username))
                .perform(typeText("username"))
                .perform(closeSoftKeyboard())
        onView(withId(android.R.id.button1)).perform((click()))

As detailed more thoroughly by this answer.

CorayThan
  • 17,174
  • 28
  • 113
  • 161
  • I don't know if it's a new thing or not, but `androidx.test.espresso.action.ViewActions` has a method `closeSoftKeyboard()' – nasch Nov 30 '19 at 01:26
  • There is no need to wrap the `closeSoftKeyBoard()` call with `perform()` either – Chisko Oct 14 '22 at 22:29
3

The good thing about the last update is it allows you to set permissions before each test, so that you don't have to click the dialog (this speeds up testing by a lot!)

Use the following rule (e.g. for location/storage.. substitute these with the permissions you need obviously)

@Rule
  public GrantPermissionRule runtimePermissionRule = GrantPermissionRule.grant(
      ACCESS_FINE_LOCATION, READ_EXTERNAL_STORAGE);
Emmaaa
  • 300
  • 2
  • 7
3

In AlertController class, Android OS sets ids to AlertDialog buttons. Check the setupButtons method. At the time of this writing, for example, the positive button id is 16908313. So you can write something like this

onView(withId(DIALOG_POSITIVE_BUTTON_ID)).check(matches(isDisplayed()));

where DIALOG_POSITIVE_BUTTON_ID = 16908313

It is also worked for me with the negative button

NovDanil
  • 51
  • 8