131eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi/*
231eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi * Copyright (C) 2016 The Android Open Source Project
331eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi *
431eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi * Licensed under the Apache License, Version 2.0 (the "License");
531eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi * you may not use this file except in compliance with the License.
631eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi * You may obtain a copy of the License at
731eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi *
831eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi *      http://www.apache.org/licenses/LICENSE-2.0
931eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi *
1031eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi * Unless required by applicable law or agreed to in writing, software
1131eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi * distributed under the License is distributed on an "AS IS" BASIS,
1231eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi * See the License for the specific language governing permissions and
1431eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi * limitations under the License
1531eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi */
1631eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
1731eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagipackage android.widget.espresso;
1831eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
1931eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport static android.support.test.espresso.Espresso.onView;
2031eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport static android.support.test.espresso.assertion.ViewAssertions.matches;
2131eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport static android.support.test.espresso.matcher.RootMatchers.withDecorView;
2231eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
2331eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
2431eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport static android.support.test.espresso.matcher.ViewMatchers.withId;
2531eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport static android.support.test.espresso.matcher.ViewMatchers.withText;
2631eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
2731eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport org.hamcrest.Matcher;
2831eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
2931eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport android.support.test.espresso.NoMatchingRootException;
3031eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport android.support.test.espresso.NoMatchingViewException;
3131eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport android.support.test.espresso.UiController;
3231eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport android.support.test.espresso.ViewAction;
3331eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport android.support.test.espresso.ViewInteraction;
3431eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport android.support.test.espresso.action.GeneralLocation;
3531eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport android.support.test.espresso.action.Press;
3631eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport android.support.test.espresso.action.Tap;
3731eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagiimport android.view.View;
3831eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
3931eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagipublic final class SuggestionsPopupwindowUtils {
4031eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    private static final int id = com.android.internal.R.id.suggestionWindowContainer;
4131eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
4231eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    private SuggestionsPopupwindowUtils() {};
4331eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
4431eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    public static ViewInteraction onSuggestionsPopup() {
4531eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        return onView(withId(id)).inRoot(withDecorView(hasDescendant(withId(id))));
4631eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    }
4731eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
4831eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    private static ViewInteraction onSuggestionsPopupItem(Matcher<View> matcher) {
4931eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        return onView(matcher).inRoot(withDecorView(hasDescendant(withId(id))));
5031eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    }
5131eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
5231eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    /**
5331eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     * Asserts that the suggestions popup is displayed on screen.
5431eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     *
5531eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     * @throws AssertionError if the assertion fails
5631eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     */
5731eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    public static void assertSuggestionsPopupIsDisplayed() {
5831eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        onSuggestionsPopup().check(matches(isDisplayed()));
5931eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    }
6031eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
6131eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    /**
6231eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     * Asserts that the suggestions popup is not displayed on screen.
6331eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     *
6431eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     * @throws AssertionError if the assertion fails
6531eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     */
6631eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    public static void assertSuggestionsPopupIsNotDisplayed() {
6731eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        try {
6831eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi            onSuggestionsPopup().check(matches(isDisplayed()));
6931eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        } catch (NoMatchingRootException | NoMatchingViewException | AssertionError e) {
7031eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi            return;
7131eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        }
7231eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        throw new AssertionError("Suggestions popup is displayed");
7331eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    }
7431eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
7531eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    /**
7631eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     * Asserts that the suggestions popup contains the specified item.
7731eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     *
7831eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     * @param itemLabel label of the item.
7931eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     * @throws AssertionError if the assertion fails
8031eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     */
8131eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    public static void assertSuggestionsPopupContainsItem(String itemLabel) {
8231eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        onSuggestionsPopupItem(withText(itemLabel)).check(matches(isDisplayed()));
8331eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    }
8431eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
8531eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    /**
8631eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     * Click on the specified item in the suggestions popup.
8731eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     *
8831eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     * @param itemLabel label of the item.
8931eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     */
9031eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    public static void clickSuggestionsPopupItem(String itemLabel) {
9131eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        onSuggestionsPopupItem(withText(itemLabel)).perform(new SuggestionItemClickAction());
9231eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    }
9331eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
9431eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    /**
9531eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     * Click action to avoid checking ViewClickAction#getConstraints().
9631eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     * TODO: Use Espresso.onData instead of this.
9731eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi     */
9831eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    private static final class SuggestionItemClickAction implements ViewAction {
9931eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        private final ViewClickAction mViewClickAction;
10031eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
10131eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        public SuggestionItemClickAction() {
10231eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi            mViewClickAction =
10331eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi                    new ViewClickAction(Tap.SINGLE, GeneralLocation.VISIBLE_CENTER, Press.FINGER);
10431eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        }
10531eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
10631eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        @Override
10731eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        public Matcher<View> getConstraints() {
10831eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi            return isDisplayed();
10931eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        }
11031eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
11131eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        @Override
11231eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        public String getDescription() {
11331eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi            return mViewClickAction.getDescription();
11431eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        }
11531eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi
11631eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        @Override
11731eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        public void perform(UiController uiController, View view) {
11831eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi            mViewClickAction.perform(uiController, view);
11931eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi        }
12031eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi    }
12131eb74fb2bc33aea6a8054c861a6e7aac7c41f4bKeisuke Kuroyanagi}
122