diff -r 000000000000 -r 6474c204b198 mobile/android/base/tests/AboutHomeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mobile/android/base/tests/AboutHomeTest.java Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,303 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.tests; + +import java.util.ArrayList; + +import org.mozilla.gecko.Actions; + +import android.support.v4.view.ViewPager; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.TabWidget; +import android.widget.TextView; + +import com.jayway.android.robotium.solo.Condition; + +/** + * This class is an extension of BaseTest that helps with interaction with about:home + * 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 + * The purpose of this class is to collect all the logically connected methods that deal with about:home + * To use any of these methods in your test make sure it extends AboutHomeTest instead of BaseTest + */ +abstract class AboutHomeTest extends PixelTest { + protected enum AboutHomeTabs {HISTORY, MOST_RECENT, TABS_FROM_LAST_TIME, TOP_SITES, BOOKMARKS, READING_LIST}; + private ArrayList aboutHomeTabs = new ArrayList() {{ + add("TOP_SITES"); + add("BOOKMARKS"); + add("READING_LIST"); + }}; + + + @Override + public void setUp() throws Exception { + super.setUp(); + + if (aboutHomeTabs.size() < 4) { + // Update it for tablets vs. phones. + if (mDevice.type.equals("phone")) { + aboutHomeTabs.add(0, AboutHomeTabs.HISTORY.toString()); + } else { + aboutHomeTabs.add(AboutHomeTabs.HISTORY.toString()); + } + } + } + + /** + * FIXME: Write new versions of these methods and update their consumers to use the new about:home pages. + */ + protected ListView getHistoryList(String waitText, int expectedChildCount) { + return null; + } + protected ListView getHistoryList(String waitText) { + return null; + } + + // Returns true if the bookmark is displayed in the bookmarks tab, false otherwise - does not check in folders + protected void isBookmarkDisplayed(final String url) { + boolean isCorrect = waitForTest(new BooleanTest() { + @Override + public boolean test() { + View bookmark = getDisplayedBookmark(url); + return bookmark != null; + } + }, MAX_WAIT_MS); + + mAsserter.ok(isCorrect, "Checking that " + url + " displayed as a bookmark", url + " displayed"); + } + + // Loads a bookmark by tapping on the bookmark view in the Bookmarks tab + protected void loadBookmark(String url) { + View bookmark = getDisplayedBookmark(url); + if (bookmark != null) { + Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded"); + mSolo.clickOnView(bookmark); + contentEventExpecter.blockForEvent(); + contentEventExpecter.unregisterListener(); + } else { + mAsserter.ok(false, url + " is not one of the displayed bookmarks", "Please make sure the url provided is bookmarked"); + } + } + + // Opens the bookmark context menu by long-tapping on it + protected void openBookmarkContextMenu(String url) { + View bookmark = getDisplayedBookmark(url); + if (bookmark != null) { + mSolo.waitForView(bookmark); + mSolo.clickLongOnView(bookmark, LONG_PRESS_TIME); + mSolo.waitForDialogToOpen(); + } else { + mAsserter.ok(false, url + " is not one of the displayed bookmarks", "Please make sure the url provided is bookmarked"); + } + } + + // @return the View associated with bookmark for the provided url or null if the link is not bookmarked + protected View getDisplayedBookmark(String url) { + openAboutHomeTab(AboutHomeTabs.BOOKMARKS); + mSolo.hideSoftKeyboard(); + getInstrumentation().waitForIdleSync(); + ListView bookmarksTabList = findListViewWithTag("bookmarks"); + waitForNonEmptyListToLoad(bookmarksTabList); + ListAdapter adapter = bookmarksTabList.getAdapter(); + if (adapter != null) { + for (int i = 0; i < adapter.getCount(); i++ ) { + // I am unable to click the view taken with getView for some reason so getting the child at i + bookmarksTabList.smoothScrollToPosition(i); + View bookmarkView = bookmarksTabList.getChildAt(i); + if (bookmarkView instanceof android.widget.LinearLayout) { + ViewGroup bookmarkItemView = (ViewGroup) bookmarkView; + for (int j = 0 ; j < bookmarkItemView.getChildCount(); j++) { + View bookmarkContent = bookmarkItemView.getChildAt(j); + if (bookmarkContent instanceof android.widget.LinearLayout) { + ViewGroup bookmarkItemLayout = (ViewGroup) bookmarkContent; + for (int k = 0 ; k < bookmarkItemLayout.getChildCount(); k++) { + // Both the title and url are represented as text views so we can cast the view without any issues + TextView bookmarkTextContent = (TextView)bookmarkItemLayout.getChildAt(k); + if (url.equals(bookmarkTextContent.getText().toString())) { + return bookmarkView; + } + } + } + } + } + } + } + return null; + } + + /** + * Waits for the given ListView to have a non-empty adapter and be populated + * with a minimum number of items. + * + * This method will return false if the given ListView or its adapter is null, + * or if the ListView does not have the minimum number of items. + */ + protected boolean waitForListToLoad(final ListView listView, final int minSize) { + Condition listWaitCondition = new Condition() { + @Override + public boolean isSatisfied() { + if (listView == null) { + return false; + } + + final ListAdapter adapter = listView.getAdapter(); + if (adapter == null) { + return false; + } + + return (listView.getCount() - listView.getHeaderViewsCount() >= minSize); + } + }; + return waitForCondition(listWaitCondition, MAX_WAIT_MS); + } + + protected boolean waitForNonEmptyListToLoad(final ListView listView) { + return waitForListToLoad(listView, 1); + } + + /** + * Get an active ListView with the specified tag . + * + * This method uses the predefined tags in HomePager. + */ + protected final ListView findListViewWithTag(String tag) { + for (ListView listView : mSolo.getCurrentViews(ListView.class)) { + final String listTag = (String) listView.getTag(); + if (TextUtils.isEmpty(listTag)) { + continue; + } + + if (TextUtils.equals(listTag, tag)) { + return listView; + } + } + + return null; + } + + // A wait in order for the about:home tab to be rendered after drag/tab selection + private void waitForAboutHomeTab(final int tabIndex) { + boolean correctTab = waitForCondition(new Condition() { + @Override + public boolean isSatisfied() { + ViewPager pager = (ViewPager)mSolo.getView(ViewPager.class, 0); + return (pager.getCurrentItem() == tabIndex); + } + }, MAX_WAIT_MS); + mAsserter.ok(correctTab, "Checking that the correct tab is displayed", "The " + aboutHomeTabs.get(tabIndex) + " tab is displayed"); + } + + private void clickAboutHomeTab(AboutHomeTabs tab) { + mSolo.clickOnText(tab.toString().replace("_", " ")); + } + + /** + * Swipes to an about:home tab. + * @param int swipeVector Value and direction to swipe (go left for negative, right for positive). + */ + private void swipeAboutHome(int swipeVector) { + // Increase swipe width, which will especially impact tablets. + int swipeWidth = mDriver.getGeckoWidth() - 1; + int swipeHeight = mDriver.getGeckoHeight() / 2; + + if (swipeVector >= 0) { + // Emulate swipe motion from right to left. + for (int i = 0; i < swipeVector; i++) { + mActions.drag(swipeWidth, 0, swipeHeight, swipeHeight); + mSolo.sleep(100); + } + } else { + // Emulate swipe motion from left to right. + for (int i = 0; i > swipeVector; i--) { + mActions.drag(0, swipeWidth, swipeHeight, swipeHeight); + mSolo.sleep(100); + } + } + } + + /** + * This method can be used to open the different tabs of about:home. + * + * @param AboutHomeTabs enum item {MOST_RECENT, TABS_FROM_LAST_TIME, TOP_SITES, BOOKMARKS, READING_LIST} + */ + protected void openAboutHomeTab(AboutHomeTabs tab) { + focusUrlBar(); + ViewPager pager = (ViewPager)mSolo.getView(ViewPager.class, 0); + final int currentTabIndex = pager.getCurrentItem(); + int tabOffset; + + // Handle tablets by just clicking the visible tab title. + if (mDevice.type.equals("tablet")) { + if (AboutHomeTabs.MOST_RECENT == tab || AboutHomeTabs.TABS_FROM_LAST_TIME == tab) { + tabOffset = aboutHomeTabs.indexOf(AboutHomeTabs.HISTORY.toString()) - currentTabIndex; + swipeAboutHome(tabOffset); + waitForAboutHomeTab(aboutHomeTabs.indexOf(StringHelper.HISTORY_LABEL)); + TabWidget tabwidget = (TabWidget)mSolo.getView(TabWidget.class, 0); + + switch (tab) { + case MOST_RECENT: { + mSolo.clickOnView(tabwidget.getChildAt(0)); + // We can determine if we are on the MOST_RECENT tab only if pages were first visited during the test + 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"); + break; + } + case TABS_FROM_LAST_TIME: { + mSolo.clickOnView(tabwidget.getChildAt(1)); + 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"); + break; + } + } + } else { + clickAboutHomeTab(tab); + } + return; + } + + // Handle phones (non-tablets). + tabOffset = aboutHomeTabs.indexOf(tab.toString()) - currentTabIndex; + switch (tab) { + case TOP_SITES : { + swipeAboutHome(tabOffset); + waitForAboutHomeTab(aboutHomeTabs.indexOf(tab.toString())); + break; + } + case BOOKMARKS : { + swipeAboutHome(tabOffset); + waitForAboutHomeTab(aboutHomeTabs.indexOf(tab.toString())); + break; + } + case MOST_RECENT: { + // MOST_RECENT is contained in the HISTORY tab. + tabOffset = aboutHomeTabs.indexOf(AboutHomeTabs.HISTORY.toString()) - currentTabIndex; + swipeAboutHome(tabOffset); + waitForAboutHomeTab(aboutHomeTabs.indexOf(StringHelper.HISTORY_LABEL)); + TabWidget tabwidget = (TabWidget)mSolo.getView(TabWidget.class, 0); + mSolo.clickOnView(tabwidget.getChildAt(0)); + // We can determine if we are on the MOST_RECENT tab only if pages were first visited during the test + 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"); + break; + } + case TABS_FROM_LAST_TIME: { + // TABS_FROM_LAST_TIME is contained in the HISTORY tab. + tabOffset = aboutHomeTabs.indexOf(AboutHomeTabs.HISTORY.toString()) - currentTabIndex; + swipeAboutHome(tabOffset); + waitForAboutHomeTab(aboutHomeTabs.indexOf(StringHelper.HISTORY_LABEL)); + TabWidget tabwidget = (TabWidget)mSolo.getView(TabWidget.class, 0); + mSolo.clickOnView(tabwidget.getChildAt(1)); + 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"); + break; + } + case READING_LIST: { + swipeAboutHome(tabOffset); + waitForAboutHomeTab(aboutHomeTabs.indexOf(tab.toString())); + break; + } + + } + } +}