15e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay/* 25e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * Copyright (C) 2015 The Android Open Source Project 35e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * 45e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * Licensed under the Apache License, Version 2.0 (the "License"); 55e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * you may not use this file except in compliance with the License. 65e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * You may obtain a copy of the License at 75e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * 85e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * http://www.apache.org/licenses/LICENSE-2.0 95e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * 105e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * Unless required by applicable law or agreed to in writing, software 115e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * distributed under the License is distributed on an "AS IS" BASIS, 125e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * See the License for the specific language governing permissions and 145e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * limitations under the License. 155e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay */ 165e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 175e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKaypackage com.android.documentsui.bots; 185e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 195e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport static junit.framework.Assert.assertEquals; 205e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport static junit.framework.Assert.assertNotNull; 215e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport static junit.framework.Assert.assertTrue; 22743bc1befcf88af802a686c35a4c4afc961f616eSteve McKayimport static junit.framework.Assert.fail; 2328bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan 24fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Linimport android.app.UiAutomation; 255e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport android.content.Context; 261273913f4ac0a272150be6c6bd7b0c6760e531b8Ben Linimport android.graphics.Point; 2728bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tanimport android.graphics.Rect; 28fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Linimport android.os.SystemClock; 295e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport android.support.test.uiautomator.By; 305e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport android.support.test.uiautomator.BySelector; 315e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport android.support.test.uiautomator.Configurator; 325e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport android.support.test.uiautomator.UiDevice; 335e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport android.support.test.uiautomator.UiObject; 345e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport android.support.test.uiautomator.UiObject2; 355e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport android.support.test.uiautomator.UiObjectNotFoundException; 365e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport android.support.test.uiautomator.UiSelector; 375e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport android.support.test.uiautomator.Until; 38fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Linimport android.view.InputDevice; 39515e51391722649479b6bac357fd363ea17de1f7Ben Linimport android.view.KeyEvent; 405e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport android.view.MotionEvent; 4128bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tanimport android.view.View; 422f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Linimport android.widget.ImageView; 435e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 445e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport java.util.ArrayList; 455e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport java.util.Arrays; 465e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport java.util.List; 475e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKayimport java.util.regex.Pattern; 485e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 495e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay/** 505e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * A test helper class that provides support for controlling directory list 515e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay * and making assertions against the state of it. 525e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay */ 5385ec0d676297724f211213c7cb188839f1d3601bSteve McKaypublic class DirectoryListBot extends Bots.BaseBot { 5428bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan private static final String DIR_CONTAINER_ID = "com.android.documentsui:id/container_directory"; 555e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay private static final String DIR_LIST_ID = "com.android.documentsui:id/dir_list"; 565e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 575e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay private static final BySelector SNACK_DELETE = 585e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay By.desc(Pattern.compile("^Deleting [0-9]+ file.+")); 59fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin private UiAutomation mAutomation; 605e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 61fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin public DirectoryListBot( 62fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin UiDevice device, UiAutomation automation, Context context, int timeout) { 635e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay super(device, context, timeout); 64fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin mAutomation = automation; 655e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 665e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 675e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public void assertDocumentsCount(int count) throws UiObjectNotFoundException { 685e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay UiObject docsList = findDocumentsList(); 695e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay assertEquals(count, docsList.getChildCount()); 705e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 715e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 725e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public void assertDocumentsPresent(String... labels) throws UiObjectNotFoundException { 735e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay List<String> absent = new ArrayList<>(); 745e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay for (String label : labels) { 755e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay if (!findDocument(label).exists()) { 765e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay absent.add(label); 775e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 785e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 795e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay if (!absent.isEmpty()) { 80743bc1befcf88af802a686c35a4c4afc961f616eSteve McKay fail("Expected documents " + Arrays.asList(labels) 815e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay + ", but missing " + absent); 825e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 835e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 845e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 855e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public void assertDocumentsAbsent(String... labels) throws UiObjectNotFoundException { 865e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay List<String> found = new ArrayList<>(); 875e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay for (String label : labels) { 885e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay if (findDocument(label).exists()) { 895e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay found.add(label); 905e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 915e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 925e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay if (!found.isEmpty()) { 93743bc1befcf88af802a686c35a4c4afc961f616eSteve McKay fail("Expected documents not present" + Arrays.asList(labels) 945e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay + ", but present " + found); 955e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 965e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 975e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 985e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public void assertDocumentsCountOnList(boolean exists, int count) throws UiObjectNotFoundException { 995e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay UiObject docsList = findDocumentsList(); 1005e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay assertEquals(exists, docsList.exists()); 1015e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay if(docsList.exists()) { 1025e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay assertEquals(count, docsList.getChildCount()); 1035e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 1045e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 1055e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 10628bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin public void assertHeaderMessageText(String message) throws UiObjectNotFoundException { 10728bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin UiObject messageTextView = findHeaderMessageTextView(); 1085e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay assertTrue(messageTextView.exists()); 1095e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 1105e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay String msg = String.valueOf(message); 111f085da0311b87dc1d06975f3fdf48f26a37a2d14Ben Lin assertEquals(msg, messageTextView.getText()); 11228bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin } 11328bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin 11428bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin /** 11528bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin * Checks against placeholder text. Placeholder can be Empty page, No results page, or the 11628bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin * "Hourglass" page (ie. something-went-wrong page). 11728bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin */ 11828bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin public void assertPlaceholderMessageText(String message) throws UiObjectNotFoundException { 11928bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin UiObject messageTextView = findPlaceholderMessageTextView(); 12028bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin assertTrue(messageTextView.exists()); 12128bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin 12228bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin String msg = String.valueOf(message); 12328bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin assertEquals(msg, messageTextView.getText()); 12428bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin 12528bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin } 1265e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 12728bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin private UiObject findHeaderMessageTextView() { 12828bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin return findObject( 12928bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin DIR_CONTAINER_ID, 13028bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin "com.android.documentsui:id/message_textview"); 1315e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 1325e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 13328bf1424fa8b38b61b0d55763dd03cb8f7685064Ben Lin private UiObject findPlaceholderMessageTextView() { 1345e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay return findObject( 13528bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan DIR_CONTAINER_ID, 1365e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay "com.android.documentsui:id/message"); 1375e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 1385e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 1395e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public void assertSnackbar(int id) { 1405e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay assertNotNull(getSnackbar(mContext.getString(id))); 1415e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 1425e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 1435e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public void openDocument(String label) throws UiObjectNotFoundException { 1445e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay int toolType = Configurator.getInstance().getToolType(); 1455e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_FINGER); 1465e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay UiObject doc = findDocument(label); 1475e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay doc.click(); 1485e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay Configurator.getInstance().setToolType(toolType); 1495e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 1505e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 1515e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public void clickDocument(String label) throws UiObjectNotFoundException { 1525e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay findDocument(label).click(); 1535e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 1545e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 155e5edf047145c916ac5b4696ddd7f14f5c2dbaf40Ben Lin /** 156e5edf047145c916ac5b4696ddd7f14f5c2dbaf40Ben Lin * @param label The filename of the document 157e5edf047145c916ac5b4696ddd7f14f5c2dbaf40Ben Lin * @param number Which nth document it is. The number corresponding to "n selected" 158e5edf047145c916ac5b4696ddd7f14f5c2dbaf40Ben Lin */ 159e5edf047145c916ac5b4696ddd7f14f5c2dbaf40Ben Lin public void selectDocument(String label, int number) throws UiObjectNotFoundException { 16085ec0d676297724f211213c7cb188839f1d3601bSteve McKay waitForDocument(label); 1612f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin UiObject2 selectionHotspot = findSelectionHotspot(label); 1622f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin selectionHotspot.click(); 163e5edf047145c916ac5b4696ddd7f14f5c2dbaf40Ben Lin 164e5edf047145c916ac5b4696ddd7f14f5c2dbaf40Ben Lin // wait until selection is fully done to avoid future click being registered as double 165e5edf047145c916ac5b4696ddd7f14f5c2dbaf40Ben Lin // clicking 166e5edf047145c916ac5b4696ddd7f14f5c2dbaf40Ben Lin assertSelection(number); 1672f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin } 1682f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin 1692f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin public UiObject2 findSelectionHotspot(String label) { 1702f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin final BySelector list = By.res(DIR_LIST_ID); 1712f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin 1722f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin BySelector selector = By.hasChild(By.text(label)); 1732f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin UiObject2 parent = mDevice.findObject(list).findObject(selector); 1742f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin if (parent.getClassName().equals("android.widget.LinearLayout")) { 1752f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin // For list mode, the parent of the textView does not contain the selector icon, but the 1762f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin // grandparent of the textView does 1772f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin // Gotta go one more level up 1782f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin selector = By.hasDescendant(By.text(label).depth(2)); 1792f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin parent = mDevice.findObject(list).findObject(selector); 1802f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin } 1812f22afa82f4d3598a20ad3fa79fd11fd0c859e02Ben Lin return parent.findObject(By.clazz(ImageView.class)); 1825e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 1835e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 184515e51391722649479b6bac357fd363ea17de1f7Ben Lin public void copyFilesToClipboard(String...labels) throws UiObjectNotFoundException { 185515e51391722649479b6bac357fd363ea17de1f7Ben Lin for (String label: labels) { 186515e51391722649479b6bac357fd363ea17de1f7Ben Lin clickDocument(label); 187515e51391722649479b6bac357fd363ea17de1f7Ben Lin } 188515e51391722649479b6bac357fd363ea17de1f7Ben Lin mDevice.pressKeyCode(KeyEvent.KEYCODE_C, KeyEvent.META_CTRL_ON); 189515e51391722649479b6bac357fd363ea17de1f7Ben Lin } 190515e51391722649479b6bac357fd363ea17de1f7Ben Lin 191515e51391722649479b6bac357fd363ea17de1f7Ben Lin public void pasteFilesFromClipboard() { 192515e51391722649479b6bac357fd363ea17de1f7Ben Lin mDevice.pressKeyCode(KeyEvent.KEYCODE_V, KeyEvent.META_CTRL_ON); 193515e51391722649479b6bac357fd363ea17de1f7Ben Lin } 194515e51391722649479b6bac357fd363ea17de1f7Ben Lin 1955e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public UiObject2 getSnackbar(String message) { 1965e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay return mDevice.wait(Until.findObject(By.text(message)), mTimeout); 1975e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 1985e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 1995e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public void waitForDeleteSnackbar() { 2005e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay mDevice.wait(Until.findObject(SNACK_DELETE), mTimeout); 2015e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 2025e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 2035e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public void waitForDeleteSnackbarGone() { 2045e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay // wait a little longer for snackbar to go away, as it disappears after a timeout. 2055e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay mDevice.wait(Until.gone(SNACK_DELETE), mTimeout * 2); 2065e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 2075e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 2085e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public void waitForDocument(String label) throws UiObjectNotFoundException { 2095e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay findDocument(label).waitForExists(mTimeout); 2105e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 2115e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 2125e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public UiObject findDocument(String label) throws UiObjectNotFoundException { 2135e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay final UiSelector docList = new UiSelector().resourceId( 21428bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan DIR_CONTAINER_ID).childSelector( 2155e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay new UiSelector().resourceId(DIR_LIST_ID)); 2165e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 2175e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay // Wait for the first list item to appear 2185e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay new UiObject(docList.childSelector(new UiSelector())).waitForExists(mTimeout); 2195e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 2205e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay // new UiScrollable(docList).scrollIntoView(new UiSelector().text(label)); 2215e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay return mDevice.findObject(docList.childSelector(new UiSelector().text(label))); 2225e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 2235e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 2245e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public boolean hasDocuments(String... labels) throws UiObjectNotFoundException { 2255e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay for (String label : labels) { 2265e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay if (!findDocument(label).exists()) { 2275e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay return false; 2285e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 2295e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 2305e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay return true; 2315e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 2325e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 23326819d7d31185b15db93e614766d7b717b98e97fBen Lin public void assertFirstDocumentHasFocus() throws UiObjectNotFoundException { 23426819d7d31185b15db93e614766d7b717b98e97fBen Lin final UiSelector docList = new UiSelector().resourceId( 23528bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan DIR_CONTAINER_ID).childSelector( 23626819d7d31185b15db93e614766d7b717b98e97fBen Lin new UiSelector().resourceId(DIR_LIST_ID)); 23726819d7d31185b15db93e614766d7b717b98e97fBen Lin 23826819d7d31185b15db93e614766d7b717b98e97fBen Lin // Wait for the first list item to appear 23926819d7d31185b15db93e614766d7b717b98e97fBen Lin UiObject doc = new UiObject(docList.childSelector(new UiSelector())); 24026819d7d31185b15db93e614766d7b717b98e97fBen Lin doc.waitForExists(mTimeout); 24126819d7d31185b15db93e614766d7b717b98e97fBen Lin 24226819d7d31185b15db93e614766d7b717b98e97fBen Lin assertTrue(doc.isFocused()); 24326819d7d31185b15db93e614766d7b717b98e97fBen Lin } 24426819d7d31185b15db93e614766d7b717b98e97fBen Lin 245811777ecf0bc23cb698dad6d9e29a5956a6f54ecTomasz Mikolajewski public UiObject findDocumentsList() { 2465e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay return findObject( 24728bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan DIR_CONTAINER_ID, 2485e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay DIR_LIST_ID); 2495e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 2505e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay 2515e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay public void assertHasFocus() { 2525e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay assertHasFocus(DIR_LIST_ID); 2535e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay } 25428bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan 2551273913f4ac0a272150be6c6bd7b0c6760e531b8Ben Lin public void assertSelection(int numSelected) { 2561273913f4ac0a272150be6c6bd7b0c6760e531b8Ben Lin String assertSelectionText = numSelected + " selected"; 2571273913f4ac0a272150be6c6bd7b0c6760e531b8Ben Lin UiObject2 selectionText = mDevice.wait( 2581273913f4ac0a272150be6c6bd7b0c6760e531b8Ben Lin Until.findObject(By.text(assertSelectionText)), mTimeout); 2591273913f4ac0a272150be6c6bd7b0c6760e531b8Ben Lin assertTrue(selectionText != null); 2601273913f4ac0a272150be6c6bd7b0c6760e531b8Ben Lin } 2611273913f4ac0a272150be6c6bd7b0c6760e531b8Ben Lin 26228bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan public void assertOrder(String[] dirs, String[] files) throws UiObjectNotFoundException { 26328bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan for (int i = 0; i < dirs.length - 1; ++i) { 26428bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan assertOrder(dirs[i], dirs[i + 1]); 26528bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan } 26628bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan 26728bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan if (dirs.length > 0 && files.length > 0) { 26828bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan assertOrder(dirs[dirs.length - 1], files[0]); 26928bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan } 27028bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan 27128bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan for (int i = 0; i < files.length - 1; ++i) { 27228bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan assertOrder(files[i], files[i + 1]); 27328bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan } 27428bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan } 27528bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan 276fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin public void rightClickDocument(String label) throws UiObjectNotFoundException { 277fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin Rect startCoord = findDocument(label).getBounds(); 278fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin rightClickDocument(new Point(startCoord.centerX(), startCoord.centerY())); 279fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin } 280fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 281fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin public void rightClickDocument(Point point) throws UiObjectNotFoundException { 282fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin //TODO: Use Espresso instead of doing the events mock ourselves 283fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin MotionEvent motionDown = getTestMotionEvent( 284fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin MotionEvent.ACTION_DOWN, 285fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin MotionEvent.BUTTON_SECONDARY, 286fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin MotionEvent.TOOL_TYPE_MOUSE, 287fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin InputDevice.SOURCE_MOUSE, 288fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin point.x, 289fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin point.y); 290fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin mAutomation.injectInputEvent(motionDown, true); 291fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin SystemClock.sleep(100); 292fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 293fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin MotionEvent motionUp = getTestMotionEvent( 294fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin MotionEvent.ACTION_UP, 295fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin MotionEvent.BUTTON_SECONDARY, 296fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin MotionEvent.TOOL_TYPE_MOUSE, 297fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin InputDevice.SOURCE_MOUSE, 298fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin point.x, 299fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin point.y); 300fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 301fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin mAutomation.injectInputEvent(motionUp, true); 302fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin } 303fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 304fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin private MotionEvent getTestMotionEvent( 305fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin int action, int buttonState, int toolType, int source, int x, int y) { 306fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin long eventTime = SystemClock.uptimeMillis(); 307fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 308fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin MotionEvent.PointerProperties[] pp = {new MotionEvent.PointerProperties()}; 309fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin pp[0].clear(); 310fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin pp[0].id = 0; 311fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin pp[0].toolType = toolType; 312fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 313fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin MotionEvent.PointerCoords[] pointerCoords = {new MotionEvent.PointerCoords()}; 314fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin pointerCoords[0].clear(); 315fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin pointerCoords[0].x = x; 316fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin pointerCoords[0].y = y; 317fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin pointerCoords[0].pressure = 0; 318fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin pointerCoords[0].size = 1; 319fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 320fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin return MotionEvent.obtain( 321fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin eventTime, 322fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin eventTime, 323fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin action, 324fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 1, 325fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin pp, 326fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin pointerCoords, 327fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 0, 328fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin buttonState, 329fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 1f, 330fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 1f, 331fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 0, 332fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 0, 333fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin source, 334fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 0); 335fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin } 336fa1e1360999a7ca6d78eb1a2fd560196fe0b4dbbBen Lin 33728bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan private void assertOrder(String first, String second) throws UiObjectNotFoundException { 33828bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan 33928bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan final UiObject firstObj = findDocument(first); 34028bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan final UiObject secondObj = findDocument(second); 34128bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan 34228bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan final int layoutDirection = mContext.getResources().getConfiguration().getLayoutDirection(); 34328bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan final Rect firstBound = firstObj.getVisibleBounds(); 34428bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan final Rect secondBound = secondObj.getVisibleBounds(); 34528bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan if (layoutDirection == View.LAYOUT_DIRECTION_LTR) { 34628bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan assertTrue( 34728bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan "\"" + first + "\" is not located above or to the left of \"" + second 34828bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan + "\" in LTR", 34928bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan firstBound.bottom < secondBound.top || firstBound.right < secondBound.left); 35028bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan } else { 35128bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan assertTrue( 35228bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan "\"" + first + "\" is not located above or to the right of \"" + second + 35328bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan "\" in RTL", 35428bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan firstBound.bottom < secondBound.top || firstBound.left > secondBound.right); 35528bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan } 35628bbd8defa2ad532d9ff1bc4d8a9ae01b574a067Garfield, Tan } 3575e1acc9f71ca4c2a07ba64ec9c050b20303993e2Steve McKay} 358