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