1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.photopicker.cts.util; 18 19 import static com.google.common.truth.Truth.assertWithMessage; 20 21 import android.text.format.DateUtils; 22 23 import androidx.test.uiautomator.UiDevice; 24 import androidx.test.uiautomator.UiObject; 25 import androidx.test.uiautomator.UiScrollable; 26 import androidx.test.uiautomator.UiSelector; 27 28 import java.util.ArrayList; 29 import java.util.List; 30 31 /** 32 * Photo Picker Utility methods for finding UI elements. 33 */ 34 public class PhotoPickerUiUtils { 35 public static final long SHORT_TIMEOUT = 5 * DateUtils.SECOND_IN_MILLIS; 36 37 public static final long TIMEOUT = 30 * DateUtils.SECOND_IN_MILLIS; 38 39 public static final String REGEX_PACKAGE_NAME = 40 "com(.google)?.android.providers.media(.module)?"; 41 42 /** 43 * Get the list of items from the photo grid list. 44 * @param itemCount if the itemCount is -1, return all matching items. Otherwise, return the 45 * item list that its size is not greater than the itemCount. 46 * @throws Exception 47 */ findItemList(int itemCount)48 public static List<UiObject> findItemList(int itemCount) throws Exception { 49 final List<UiObject> itemList = new ArrayList<>(); 50 final UiSelector gridList = new UiSelector().resourceIdMatches( 51 REGEX_PACKAGE_NAME + ":id/picker_tab_recyclerview"); 52 53 // Wait for the first item to appear 54 assertWithMessage("Timed out while waiting for first item to appear") 55 .that(new UiObject(gridList.childSelector(new UiSelector())).waitForExists(TIMEOUT)) 56 .isTrue(); 57 58 final UiSelector itemSelector = new UiSelector().resourceIdMatches( 59 REGEX_PACKAGE_NAME + ":id/icon_thumbnail"); 60 final UiScrollable grid = new UiScrollable(gridList); 61 final int childCount = grid.getChildCount(); 62 final int count = itemCount == -1 ? childCount : itemCount; 63 64 for (int i = 0; i < childCount; i++) { 65 final UiObject item = grid.getChildByInstance(itemSelector, i); 66 if (item.exists()) { 67 itemList.add(item); 68 } 69 if (itemList.size() == count) { 70 break; 71 } 72 } 73 return itemList; 74 } 75 findPreviewAddButton()76 public static UiObject findPreviewAddButton() { 77 return new UiObject(new UiSelector().resourceIdMatches( 78 REGEX_PACKAGE_NAME + ":id/preview_add_button")); 79 } 80 findPreviewAddOrSelectButton()81 public static UiObject findPreviewAddOrSelectButton() { 82 return new UiObject(new UiSelector().resourceIdMatches( 83 REGEX_PACKAGE_NAME + ":id/preview_add_or_select_button")); 84 } 85 findAddButton()86 public static UiObject findAddButton() { 87 return new UiObject(new UiSelector().resourceIdMatches( 88 REGEX_PACKAGE_NAME + ":id/button_add")); 89 } 90 findProfileButton()91 public static UiObject findProfileButton() { 92 return new UiObject(new UiSelector().resourceIdMatches( 93 REGEX_PACKAGE_NAME + ":id/profile_button")); 94 } 95 findAndClickBrowse(UiDevice uiDevice)96 public static void findAndClickBrowse(UiDevice uiDevice) throws Exception { 97 final UiObject overflowMenu = getOverflowMenuObject(uiDevice); 98 clickAndWait(uiDevice, overflowMenu); 99 100 final UiObject browseButton = new UiObject(new UiSelector().textContains("Browse")); 101 clickAndWait(uiDevice, browseButton); 102 } 103 findSettingsOverflowMenuItem(UiDevice uiDevice)104 public static UiObject findSettingsOverflowMenuItem(UiDevice uiDevice) throws Exception { 105 final UiObject overflowMenu = getOverflowMenuObject(uiDevice); 106 clickAndWait(uiDevice, overflowMenu); 107 return new UiObject(new UiSelector().textContains("Cloud media app")); 108 } 109 getOverflowMenuObject(UiDevice uiDevice)110 public static UiObject getOverflowMenuObject(UiDevice uiDevice) { 111 // Wait for overflow menu to appear. 112 verifyOverflowMenuExists(uiDevice); 113 return new UiObject(new UiSelector().description("More options")); 114 } 115 isPhotoPickerVisible()116 public static boolean isPhotoPickerVisible() { 117 return new UiObject(new UiSelector().resourceIdMatches( 118 PhotoPickerUiUtils.REGEX_PACKAGE_NAME + ":id/bottom_sheet")).waitForExists(TIMEOUT); 119 } 120 verifySettingsActionBarIsVisible()121 public static void verifySettingsActionBarIsVisible() { 122 assertWithMessage("Timed out waiting for action bar to appear") 123 .that(new UiObject(new UiSelector() 124 .resourceIdMatches(REGEX_PACKAGE_NAME + ":id/picker_settings_toolbar")) 125 .waitForExists(TIMEOUT)) 126 .isTrue(); 127 } 128 verifySettingsTitleIsVisible()129 public static void verifySettingsTitleIsVisible() { 130 assertWithMessage("Timed out waiting for settings page title to appear") 131 .that(new UiObject(new UiSelector() 132 .resourceIdMatches(REGEX_PACKAGE_NAME + ":id/picker_settings_title")) 133 .waitForExists(TIMEOUT)) 134 .isTrue(); 135 } 136 verifySettingsDescriptionIsVisible()137 public static void verifySettingsDescriptionIsVisible() { 138 assertWithMessage("Timed out waiting for settings page description to appear") 139 .that(new UiObject(new UiSelector() 140 .resourceIdMatches(REGEX_PACKAGE_NAME + ":id/picker_settings_description")) 141 .waitForExists(TIMEOUT)) 142 .isTrue(); 143 } 144 verifySettingsFragmentContainerExists()145 public static void verifySettingsFragmentContainerExists() { 146 assertWithMessage("Timed out waiting for settings fragment container to appear") 147 .that(new UiObject(new UiSelector() 148 .resourceIdMatches(REGEX_PACKAGE_NAME + ":id/settings_fragment_container")) 149 .waitForExists(TIMEOUT)) 150 .isTrue(); 151 } 152 verifyOverflowMenuExists(UiDevice uiDevice)153 private static void verifyOverflowMenuExists(UiDevice uiDevice) { 154 assertWithMessage("Timed out waiting for overflow menu to appear") 155 .that(new UiObject(new UiSelector().description("More options")) 156 .waitForExists(TIMEOUT)) 157 .isTrue(); 158 } 159 verifySettingsActivityIsVisible()160 public static void verifySettingsActivityIsVisible() { 161 // id/settings_activity_root is the root layout in activity_photo_picker_settings.xml 162 assertWithMessage("Timed out waiting for settings activity to appear") 163 .that(new UiObject(new UiSelector() 164 .resourceIdMatches(REGEX_PACKAGE_NAME + ":id/settings_activity_root")) 165 .waitForExists(TIMEOUT)) 166 .isTrue(); 167 } 168 clickAndWait(UiDevice uiDevice, UiObject uiObject)169 public static void clickAndWait(UiDevice uiDevice, UiObject uiObject) throws Exception { 170 uiObject.click(); 171 uiDevice.waitForIdle(); 172 } 173 getBannerPrimaryText()174 public static String getBannerPrimaryText() throws Exception { 175 final UiObject bannerPrimaryText = findBannerPrimaryText(); 176 assertWithMessage("Timed out waiting for the banner to appear") 177 .that(bannerPrimaryText.waitForExists(TIMEOUT)) 178 .isTrue(); 179 return bannerPrimaryText.getText(); 180 } 181 findBannerPrimaryText()182 public static UiObject findBannerPrimaryText() { 183 return new UiObject(new UiSelector().resourceIdMatches( 184 REGEX_PACKAGE_NAME + ":id/banner_primary_text")); 185 } 186 findBannerDismissButton()187 public static UiObject findBannerDismissButton() { 188 return new UiObject(new UiSelector().resourceIdMatches( 189 REGEX_PACKAGE_NAME + ":id/dismiss_button")); 190 } 191 findBannerActionButton()192 public static UiObject findBannerActionButton() { 193 return new UiObject(new UiSelector().resourceIdMatches( 194 REGEX_PACKAGE_NAME + ":id/action_button")); 195 } 196 } 197