|
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/. */ |
|
4 |
|
5 package org.mozilla.gecko.tests; |
|
6 |
|
7 import java.util.ArrayList; |
|
8 |
|
9 import org.mozilla.gecko.Actions; |
|
10 |
|
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; |
|
19 |
|
20 import com.jayway.android.robotium.solo.Condition; |
|
21 |
|
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 }}; |
|
35 |
|
36 |
|
37 @Override |
|
38 public void setUp() throws Exception { |
|
39 super.setUp(); |
|
40 |
|
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 } |
|
50 |
|
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 } |
|
60 |
|
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); |
|
70 |
|
71 mAsserter.ok(isCorrect, "Checking that " + url + " displayed as a bookmark", url + " displayed"); |
|
72 } |
|
73 |
|
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 } |
|
86 |
|
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 } |
|
98 |
|
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 } |
|
132 |
|
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 } |
|
147 |
|
148 final ListAdapter adapter = listView.getAdapter(); |
|
149 if (adapter == null) { |
|
150 return false; |
|
151 } |
|
152 |
|
153 return (listView.getCount() - listView.getHeaderViewsCount() >= minSize); |
|
154 } |
|
155 }; |
|
156 return waitForCondition(listWaitCondition, MAX_WAIT_MS); |
|
157 } |
|
158 |
|
159 protected boolean waitForNonEmptyListToLoad(final ListView listView) { |
|
160 return waitForListToLoad(listView, 1); |
|
161 } |
|
162 |
|
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 } |
|
174 |
|
175 if (TextUtils.equals(listTag, tag)) { |
|
176 return listView; |
|
177 } |
|
178 } |
|
179 |
|
180 return null; |
|
181 } |
|
182 |
|
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 } |
|
194 |
|
195 private void clickAboutHomeTab(AboutHomeTabs tab) { |
|
196 mSolo.clickOnText(tab.toString().replace("_", " ")); |
|
197 } |
|
198 |
|
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; |
|
207 |
|
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 } |
|
222 |
|
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; |
|
233 |
|
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); |
|
241 |
|
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 } |
|
260 |
|
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 } |
|
300 |
|
301 } |
|
302 } |
|
303 } |