Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 package org.mozilla.gecko.tests;
7 import java.util.ArrayList;
9 import org.mozilla.gecko.Actions;
11 import android.support.v4.view.ViewPager;
12 import android.text.TextUtils;
13 import android.view.View;
14 import android.view.ViewGroup;
15 import android.widget.ListAdapter;
16 import android.widget.ListView;
17 import android.widget.TabWidget;
18 import android.widget.TextView;
20 import com.jayway.android.robotium.solo.Condition;
22 /**
23 * This class is an extension of BaseTest that helps with interaction with about:home
24 * This class contains methods that access the different tabs from about:home, methods that get information like history and bookmarks from the database, edit and remove bookmarks and history items
25 * The purpose of this class is to collect all the logically connected methods that deal with about:home
26 * To use any of these methods in your test make sure it extends AboutHomeTest instead of BaseTest
27 */
28 abstract class AboutHomeTest extends PixelTest {
29 protected enum AboutHomeTabs {HISTORY, MOST_RECENT, TABS_FROM_LAST_TIME, TOP_SITES, BOOKMARKS, READING_LIST};
30 private ArrayList<String> aboutHomeTabs = new ArrayList<String>() {{
31 add("TOP_SITES");
32 add("BOOKMARKS");
33 add("READING_LIST");
34 }};
37 @Override
38 public void setUp() throws Exception {
39 super.setUp();
41 if (aboutHomeTabs.size() < 4) {
42 // Update it for tablets vs. phones.
43 if (mDevice.type.equals("phone")) {
44 aboutHomeTabs.add(0, AboutHomeTabs.HISTORY.toString());
45 } else {
46 aboutHomeTabs.add(AboutHomeTabs.HISTORY.toString());
47 }
48 }
49 }
51 /**
52 * FIXME: Write new versions of these methods and update their consumers to use the new about:home pages.
53 */
54 protected ListView getHistoryList(String waitText, int expectedChildCount) {
55 return null;
56 }
57 protected ListView getHistoryList(String waitText) {
58 return null;
59 }
61 // Returns true if the bookmark is displayed in the bookmarks tab, false otherwise - does not check in folders
62 protected void isBookmarkDisplayed(final String url) {
63 boolean isCorrect = waitForTest(new BooleanTest() {
64 @Override
65 public boolean test() {
66 View bookmark = getDisplayedBookmark(url);
67 return bookmark != null;
68 }
69 }, MAX_WAIT_MS);
71 mAsserter.ok(isCorrect, "Checking that " + url + " displayed as a bookmark", url + " displayed");
72 }
74 // Loads a bookmark by tapping on the bookmark view in the Bookmarks tab
75 protected void loadBookmark(String url) {
76 View bookmark = getDisplayedBookmark(url);
77 if (bookmark != null) {
78 Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded");
79 mSolo.clickOnView(bookmark);
80 contentEventExpecter.blockForEvent();
81 contentEventExpecter.unregisterListener();
82 } else {
83 mAsserter.ok(false, url + " is not one of the displayed bookmarks", "Please make sure the url provided is bookmarked");
84 }
85 }
87 // Opens the bookmark context menu by long-tapping on it
88 protected void openBookmarkContextMenu(String url) {
89 View bookmark = getDisplayedBookmark(url);
90 if (bookmark != null) {
91 mSolo.waitForView(bookmark);
92 mSolo.clickLongOnView(bookmark, LONG_PRESS_TIME);
93 mSolo.waitForDialogToOpen();
94 } else {
95 mAsserter.ok(false, url + " is not one of the displayed bookmarks", "Please make sure the url provided is bookmarked");
96 }
97 }
99 // @return the View associated with bookmark for the provided url or null if the link is not bookmarked
100 protected View getDisplayedBookmark(String url) {
101 openAboutHomeTab(AboutHomeTabs.BOOKMARKS);
102 mSolo.hideSoftKeyboard();
103 getInstrumentation().waitForIdleSync();
104 ListView bookmarksTabList = findListViewWithTag("bookmarks");
105 waitForNonEmptyListToLoad(bookmarksTabList);
106 ListAdapter adapter = bookmarksTabList.getAdapter();
107 if (adapter != null) {
108 for (int i = 0; i < adapter.getCount(); i++ ) {
109 // I am unable to click the view taken with getView for some reason so getting the child at i
110 bookmarksTabList.smoothScrollToPosition(i);
111 View bookmarkView = bookmarksTabList.getChildAt(i);
112 if (bookmarkView instanceof android.widget.LinearLayout) {
113 ViewGroup bookmarkItemView = (ViewGroup) bookmarkView;
114 for (int j = 0 ; j < bookmarkItemView.getChildCount(); j++) {
115 View bookmarkContent = bookmarkItemView.getChildAt(j);
116 if (bookmarkContent instanceof android.widget.LinearLayout) {
117 ViewGroup bookmarkItemLayout = (ViewGroup) bookmarkContent;
118 for (int k = 0 ; k < bookmarkItemLayout.getChildCount(); k++) {
119 // Both the title and url are represented as text views so we can cast the view without any issues
120 TextView bookmarkTextContent = (TextView)bookmarkItemLayout.getChildAt(k);
121 if (url.equals(bookmarkTextContent.getText().toString())) {
122 return bookmarkView;
123 }
124 }
125 }
126 }
127 }
128 }
129 }
130 return null;
131 }
133 /**
134 * Waits for the given ListView to have a non-empty adapter and be populated
135 * with a minimum number of items.
136 *
137 * This method will return false if the given ListView or its adapter is null,
138 * or if the ListView does not have the minimum number of items.
139 */
140 protected boolean waitForListToLoad(final ListView listView, final int minSize) {
141 Condition listWaitCondition = new Condition() {
142 @Override
143 public boolean isSatisfied() {
144 if (listView == null) {
145 return false;
146 }
148 final ListAdapter adapter = listView.getAdapter();
149 if (adapter == null) {
150 return false;
151 }
153 return (listView.getCount() - listView.getHeaderViewsCount() >= minSize);
154 }
155 };
156 return waitForCondition(listWaitCondition, MAX_WAIT_MS);
157 }
159 protected boolean waitForNonEmptyListToLoad(final ListView listView) {
160 return waitForListToLoad(listView, 1);
161 }
163 /**
164 * Get an active ListView with the specified tag .
165 *
166 * This method uses the predefined tags in HomePager.
167 */
168 protected final ListView findListViewWithTag(String tag) {
169 for (ListView listView : mSolo.getCurrentViews(ListView.class)) {
170 final String listTag = (String) listView.getTag();
171 if (TextUtils.isEmpty(listTag)) {
172 continue;
173 }
175 if (TextUtils.equals(listTag, tag)) {
176 return listView;
177 }
178 }
180 return null;
181 }
183 // A wait in order for the about:home tab to be rendered after drag/tab selection
184 private void waitForAboutHomeTab(final int tabIndex) {
185 boolean correctTab = waitForCondition(new Condition() {
186 @Override
187 public boolean isSatisfied() {
188 ViewPager pager = (ViewPager)mSolo.getView(ViewPager.class, 0);
189 return (pager.getCurrentItem() == tabIndex);
190 }
191 }, MAX_WAIT_MS);
192 mAsserter.ok(correctTab, "Checking that the correct tab is displayed", "The " + aboutHomeTabs.get(tabIndex) + " tab is displayed");
193 }
195 private void clickAboutHomeTab(AboutHomeTabs tab) {
196 mSolo.clickOnText(tab.toString().replace("_", " "));
197 }
199 /**
200 * Swipes to an about:home tab.
201 * @param int swipeVector Value and direction to swipe (go left for negative, right for positive).
202 */
203 private void swipeAboutHome(int swipeVector) {
204 // Increase swipe width, which will especially impact tablets.
205 int swipeWidth = mDriver.getGeckoWidth() - 1;
206 int swipeHeight = mDriver.getGeckoHeight() / 2;
208 if (swipeVector >= 0) {
209 // Emulate swipe motion from right to left.
210 for (int i = 0; i < swipeVector; i++) {
211 mActions.drag(swipeWidth, 0, swipeHeight, swipeHeight);
212 mSolo.sleep(100);
213 }
214 } else {
215 // Emulate swipe motion from left to right.
216 for (int i = 0; i > swipeVector; i--) {
217 mActions.drag(0, swipeWidth, swipeHeight, swipeHeight);
218 mSolo.sleep(100);
219 }
220 }
221 }
223 /**
224 * This method can be used to open the different tabs of about:home.
225 *
226 * @param AboutHomeTabs enum item {MOST_RECENT, TABS_FROM_LAST_TIME, TOP_SITES, BOOKMARKS, READING_LIST}
227 */
228 protected void openAboutHomeTab(AboutHomeTabs tab) {
229 focusUrlBar();
230 ViewPager pager = (ViewPager)mSolo.getView(ViewPager.class, 0);
231 final int currentTabIndex = pager.getCurrentItem();
232 int tabOffset;
234 // Handle tablets by just clicking the visible tab title.
235 if (mDevice.type.equals("tablet")) {
236 if (AboutHomeTabs.MOST_RECENT == tab || AboutHomeTabs.TABS_FROM_LAST_TIME == tab) {
237 tabOffset = aboutHomeTabs.indexOf(AboutHomeTabs.HISTORY.toString()) - currentTabIndex;
238 swipeAboutHome(tabOffset);
239 waitForAboutHomeTab(aboutHomeTabs.indexOf(StringHelper.HISTORY_LABEL));
240 TabWidget tabwidget = (TabWidget)mSolo.getView(TabWidget.class, 0);
242 switch (tab) {
243 case MOST_RECENT: {
244 mSolo.clickOnView(tabwidget.getChildAt(0));
245 // We can determine if we are on the MOST_RECENT tab only if pages were first visited during the test
246 mAsserter.ok(waitForText(StringHelper.TODAY_LABEL), "Checking that we are in the most recent tab of about:home", "We are in the most recent tab");
247 break;
248 }
249 case TABS_FROM_LAST_TIME: {
250 mSolo.clickOnView(tabwidget.getChildAt(1));
251 mAsserter.ok(waitForText(StringHelper.TABS_FROM_LAST_TIME_LABEL), "Checking that we are in the Tabs from last time tab of about:home", "We are in the Tabs from last time tab");
252 break;
253 }
254 }
255 } else {
256 clickAboutHomeTab(tab);
257 }
258 return;
259 }
261 // Handle phones (non-tablets).
262 tabOffset = aboutHomeTabs.indexOf(tab.toString()) - currentTabIndex;
263 switch (tab) {
264 case TOP_SITES : {
265 swipeAboutHome(tabOffset);
266 waitForAboutHomeTab(aboutHomeTabs.indexOf(tab.toString()));
267 break;
268 }
269 case BOOKMARKS : {
270 swipeAboutHome(tabOffset);
271 waitForAboutHomeTab(aboutHomeTabs.indexOf(tab.toString()));
272 break;
273 }
274 case MOST_RECENT: {
275 // MOST_RECENT is contained in the HISTORY tab.
276 tabOffset = aboutHomeTabs.indexOf(AboutHomeTabs.HISTORY.toString()) - currentTabIndex;
277 swipeAboutHome(tabOffset);
278 waitForAboutHomeTab(aboutHomeTabs.indexOf(StringHelper.HISTORY_LABEL));
279 TabWidget tabwidget = (TabWidget)mSolo.getView(TabWidget.class, 0);
280 mSolo.clickOnView(tabwidget.getChildAt(0));
281 // We can determine if we are on the MOST_RECENT tab only if pages were first visited during the test
282 mAsserter.ok(waitForText(StringHelper.TODAY_LABEL), "Checking that we are in the most recent tab of about:home", "We are in the most recent tab");
283 break;
284 }
285 case TABS_FROM_LAST_TIME: {
286 // TABS_FROM_LAST_TIME is contained in the HISTORY tab.
287 tabOffset = aboutHomeTabs.indexOf(AboutHomeTabs.HISTORY.toString()) - currentTabIndex;
288 swipeAboutHome(tabOffset);
289 waitForAboutHomeTab(aboutHomeTabs.indexOf(StringHelper.HISTORY_LABEL));
290 TabWidget tabwidget = (TabWidget)mSolo.getView(TabWidget.class, 0);
291 mSolo.clickOnView(tabwidget.getChildAt(1));
292 mAsserter.ok(waitForText(StringHelper.TABS_FROM_LAST_TIME_LABEL), "Checking that we are in the Tabs from last time tab of about:home", "We are in the Tabs from last time tab");
293 break;
294 }
295 case READING_LIST: {
296 swipeAboutHome(tabOffset);
297 waitForAboutHomeTab(aboutHomeTabs.indexOf(tab.toString()));
298 break;
299 }
301 }
302 }
303 }