blob: ecad0617c179aa3e26acc391c7286febb1556372 [file] [log] [blame]
Steve McKay0c3c6952015-10-26 17:03:55 -07001/*
2 * Copyright (C) 2015 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
17package com.android.documentsui;
18
Steve McKayc6a4cd82015-11-18 14:56:50 -080019import static junit.framework.Assert.assertEquals;
20
Steve McKay0c3c6952015-10-26 17:03:55 -070021import android.support.test.uiautomator.By;
22import android.support.test.uiautomator.BySelector;
23import android.support.test.uiautomator.UiDevice;
24import android.support.test.uiautomator.UiObject;
25import android.support.test.uiautomator.UiObject2;
26import android.support.test.uiautomator.UiObjectNotFoundException;
27import android.support.test.uiautomator.UiScrollable;
28import android.support.test.uiautomator.UiSelector;
29import android.support.test.uiautomator.Until;
30import android.util.Log;
31
32import junit.framework.Assert;
33
34import java.util.ArrayList;
35import java.util.Arrays;
36import java.util.List;
37import java.util.regex.Pattern;
38
39/**
40 * A test helper class that provides support for controlling DocumentsUI activities
41 * programmatically, and making assertions against the state of the UI.
42 */
43class UiBot {
44
45 private static final String TAG = "UiBot";
46
47 private static final BySelector SNACK_DELETE =
48 By.desc(Pattern.compile("^Deleting [0-9]+ file.+"));
49
50 private UiDevice mDevice;
51 private int mTimeout;
52
53 public UiBot(UiDevice device, int timeout) {
54 mDevice = device;
55 mTimeout = timeout;
56 }
57
58 UiObject findRoot(String label) throws UiObjectNotFoundException {
59 final UiSelector rootsList = new UiSelector().resourceId(
60 "com.android.documentsui:id/container_roots").childSelector(
61 new UiSelector().resourceId("android:id/list"));
62
63 // We might need to expand drawer if not visible
64 if (!new UiObject(rootsList).waitForExists(mTimeout)) {
65 Log.d(TAG, "Failed to find roots list; trying to expand");
66 final UiSelector hamburger = new UiSelector().resourceId(
67 "com.android.documentsui:id/toolbar").childSelector(
68 new UiSelector().className("android.widget.ImageButton").clickable(true));
69 new UiObject(hamburger).click();
70 }
71
72 // Wait for the first list item to appear
73 new UiObject(rootsList.childSelector(new UiSelector())).waitForExists(mTimeout);
74
75 // Now scroll around to find our item
76 new UiScrollable(rootsList).scrollIntoView(new UiSelector().text(label));
77 return new UiObject(rootsList.childSelector(new UiSelector().text(label)));
78 }
79
80 void openRoot(String label) throws UiObjectNotFoundException {
81 findRoot(label).click();
82 mDevice.waitForIdle();
83 }
84
Steve McKayc6a4cd82015-11-18 14:56:50 -080085 void assertWindowTitle(String expected) {
86 // Turns out the title field on a window does not have
87 // an id associated with it at runtime (which confuses the hell out of me)
88 // In code we address this via "android.R.id.title".
89 UiObject2 o = find(By.text(expected));
90 // It's a bit of a conceit that we then *assert* that the title
91 // is the value that we used to identify the UiObject2.
92 // If the preceeding lookup fails, this'll choke with an NPE.
93 // But given the issue described in the comment above, we're
94 // going to do it anyway. Because we shouldn't be looking up
95 // the uiobject by it's expected content :|
96 assertEquals(expected, o.getText());
97 }
98
Steve McKay0c3c6952015-10-26 17:03:55 -070099 void assertHasRoots(String... labels) throws UiObjectNotFoundException {
100 List<String> missing = new ArrayList<>();
101 for (String label : labels) {
102 if (!findRoot(label).exists()) {
103 missing.add(label);
104 }
105 }
106 if (!missing.isEmpty()) {
107 Assert.fail(
108 "Expected roots " + Arrays.asList(labels) + ", but missing " + missing);
109 }
110 }
111
112 UiObject findDocument(String label) throws UiObjectNotFoundException {
113 final UiSelector docList = new UiSelector().resourceId(
114 "com.android.documentsui:id/container_directory").childSelector(
115 new UiSelector().resourceId("com.android.documentsui:id/list"));
116
117 // Wait for the first list item to appear
118 new UiObject(docList.childSelector(new UiSelector())).waitForExists(mTimeout);
119
120 // new UiScrollable(docList).scrollIntoView(new UiSelector().text(label));
121 return mDevice.findObject(docList.childSelector(new UiSelector().text(label)));
122 }
123
124 boolean hasDocuments(String... labels) throws UiObjectNotFoundException {
125 for (String label : labels) {
126 if (!findDocument(label).exists()) {
127 return false;
128 }
129 }
130 return true;
131 }
132
133 void assertHasDocuments(String... labels) throws UiObjectNotFoundException {
134 List<String> missing = new ArrayList<>();
135 for (String label : labels) {
136 if (!findDocument(label).exists()) {
137 missing.add(label);
138 }
139 }
140 if (!missing.isEmpty()) {
141 Assert.fail(
142 "Expected documents " + Arrays.asList(labels) + ", but missing " + missing);
143 }
144 }
145
146 void clickDocument(String label) throws UiObjectNotFoundException {
147 findDocument(label).click();
148 }
149
150 void waitForDeleteSnackbar() {
151 mDevice.wait(Until.findObject(SNACK_DELETE), mTimeout);
152 }
153
154 void waitForDeleteSnackbarGone() {
155 // wait a little longer for snackbar to go away, as it disappears after a timeout.
156 mDevice.wait(Until.gone(SNACK_DELETE), mTimeout * 2);
157 }
158
159 void switchViewMode() {
160 UiObject2 mode = menuGridMode();
161 if (mode != null) {
162 mode.click();
163 } else {
164 menuListMode().click();
165 }
166 }
167
168 UiObject2 menuGridMode() {
169 // Note that we're using By.desc rather than By.res, because of b/25285770
170 return find(By.desc("Grid view"));
171 }
172
173 UiObject2 menuListMode() {
174 // Note that we're using By.desc rather than By.res, because of b/25285770
175 return find(By.desc("List view"));
176 }
177
178 UiObject2 menuDelete() {
179 return find(By.res("com.android.documentsui:id/menu_delete"));
180 }
181
182 private UiObject2 find(BySelector selector) {
183 mDevice.wait(Until.findObject(selector), mTimeout);
184 return mDevice.findObject(selector);
185 }
186}