Using Espresso how do i check the number of items in my alert Dialog
Asked Answered
C

3

5

I have an alert dialog that displays a number of items.

    private String[] choices; // populated externally

    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setItems(choices, new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            _callback.onChoiceSelected(which);
            dialog.dismiss();
        }
    });

    _dialog = builder.create();

Under different circumstances (for e.g. if you're an admin/guest) you will have a different number of "choices". In my espresso test, I'm basically trying to test the number of items present.

public void test_ViewsSetupCorrectly() {

    onView(withId(R.id.settings)).perform(click());
    onView(ViewMatchers.withChild(withClassName(Matchers.equalToIgnoringCase("TextView")))).check(matches(isDisplayed()));

    /*// What I would ideally like ... but doesn't work as well :( :
      onView(withClassName(equalToIgnoringWhiteSpace("DialogTitle"))).check(matches(hasProperty("child-count",
                                                                                                      is(new Integer(1))
                                                                                                      )));*/
}

These basically throw an exception like so:

I presume the onData call is only for performing actions? I'm not performing an action necessarily. Could anyone help me actually test this?

  com.google.android.apps.common.testing.ui.espresso.NoMatchingViewException: No views in hierarchy found matching: has child: with class name: eqIgnoringCase("TextView")
  If the target view is not part of the view hierarchy, you may need to use Espresso.onData to load it from one of the following AdapterViews:com.android.internal.app.AlertController$RecycleListView@5389ef7c

  View Hierarchy:
  +>DecorView{id=-1, visibility=VISIBLE, width=684, height=226, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
  |
  +->FrameLayout{id=-1, visibility=VISIBLE, width=684, height=226, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
  |
  +-->FrameLayout{id=16908290, res-name=content, visibility=VISIBLE, width=684, height=226, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
  |
  +--->LinearLayout{id=16908874, res-name=parentPanel, visibility=VISIBLE, width=652, height=226, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=16.0, y=0.0, child-count=4}
  |
  +---->LinearLayout{id=16908875, res-name=topPanel, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3}
  |
  +----->View{id=16908885, res-name=titleDividerTop, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
  |
  +----->LinearLayout{id=16908876, res-name=title_template, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
  |
  +------>ImageView{id=16908294, res-name=icon, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
  |
  +------>DialogTitle{id=16908877, res-name=alertTitle, visibility=VISIBLE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=, input-type=0, ime-target=false}
  |
  +----->View{id=16908878, res-name=titleDivider, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
  |
  +---->LinearLayout{id=16908882, res-name=contentPanel, visibility=VISIBLE, width=652, height=226, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
  |
  +----->RecycleListView{id=16909101, res-name=select_dialog_listview, visibility=VISIBLE, width=620, height=194, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=true, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=16.0, y=16.0, child-count=2}
  |
  +------>TextView{id=16908308, res-name=text1, visibility=VISIBLE, width=620, height=96, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=Edit Info, input-type=0, ime-target=false}
  |
  +------>TextView{id=16908308, res-name=text1, visibility=VISIBLE, width=620, height=96, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=98.0, text=Use gallery photo, input-type=0, ime-target=false}
  |
  +---->FrameLayout{id=16908884, res-name=customPanel, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
  |
  +----->FrameLayout{id=16908331, res-name=custom, visibility=VISIBLE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=0}
  |
  +---->LinearLayout{id=16908879, res-name=buttonPanel, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
  |
  +----->LinearLayout{id=-1, visibility=VISIBLE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3}
  |
  +------>Button{id=16908314, res-name=button2, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=, input-type=0, ime-target=false}
  |
  +------>Button{id=16908315, res-name=button3, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=, input-type=0, ime-target=false}
  |
  +------>Button{id=16908313, res-name=button1, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=, input-type=0, ime-target=false}
  |
  +-->ViewStub{id=16909076, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
  |
  at dalvik.system.VMStack.getThreadStackTrace(Native Method)
  at java.lang.Thread.getStackTrace(Thread.java:591)
  at com.google.android.apps.common.testing.ui.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:69)
  at com.google.android.apps.common.testing.ui.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:40)
  at com.google.android.apps.common.testing.ui.espresso.ViewInteraction.runSynchronouslyOnUiThread(ViewInteraction.java:159)
  at com.google.android.apps.common.testing.ui.espresso.ViewInteraction.check(ViewInteraction.java:133)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
  at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
  at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)
  at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:190)
  at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:175)
  at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
  at com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner.onStart(GoogleInstrumentationTestRunner.java:167)
  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1584)
Cheyney answered 22/5, 2014 at 3:35 Comment(1)
OnData should allow checks as well. Have you tried something like: onData(allOf(is(instanceOf(String.class)), equalTo(string))).atPosition(lastExpectedIndex).check(<do your check here>);Median
B
10

this is what i came up with add method to whatever custom matcher library you use.

public static Matcher<View> hasChildren(final Matcher<Integer> numChildrenMatcher) {
        return new TypeSafeMatcher<View>() {

            /**
             * matching with viewgroup.getChildCount()
             */
            @Override
            public boolean matchesSafely(View view) {
                return view instanceof ViewGroup && numChildrenMatcher.matches(((ViewGroup)view).getChildCount());
            }

            /**
             * gets the description
             */
            @Override
            public void describeTo(Description description) {
                description.appendText(" a view with # children is ");
                numChildrenMatcher.describeTo(description);
            }
        };
    }

Usage is:

int numKids = 3;  
onView(withId(R.id.view_pager)).check(matches(allOf(
                    isDisplayed(),
                    hasChildren(is(numKids))
            )));
Bauxite answered 14/12, 2015 at 12:5 Comment(0)
S
0

I have had a similar issue in the past but I was adding my own EditText control to the alert dialog. When doing it this way you can assign an ID to the view object that is being added to the dialog.

AlertDialog.Builder myDialog = new AlertDialog.Builder(this);

myDialog.setTitle(R.string.add_comment);

// Set an EditText view to get user input
final EditText input = new EditText(this);
input.setId(R.id.myEditText);
myDialog.setView(input);

The add_comment_text id is specified in an ids.xml file in res/values and then you can select this using.

onView(withId(R.id.myEditText)
Siamese answered 7/10, 2014 at 13:9 Comment(0)
H
-1

I know this is quite an old post, but it looks like what you want is something like what is described by this blog post here. You could then access the dialog with a matcher that matches the dialog view and call something such as getChildCount() or similar such method related to the dialog? Hopefully this will help someone!

Hagood answered 24/9, 2015 at 18:28 Comment(1)
That link appears to be dead.Medullary

© 2022 - 2024 — McMap. All rights reserved.