mobile/android/base/tests/AboutHomeTest.java.in
author Ed Morley <emorley@mozilla.com>
Tue, 15 Oct 2013 17:22:34 +0100
changeset 165652 79360e1c33a56ca48ac62548c7f436fa445a04ab
parent 165433 0b6f43cbb7ddaea2bbc357847bb2e7fc331d8f09
child 165661 8ac8f0ebecddcc193900d8761b8fa83bae0e2b42
permissions -rw-r--r--
Backed out changeset 0b6f43cbb7dd (bug 899187) for causing a couple of new intermittent failures

#filter substitution
package @ANDROID_PACKAGE_NAME@.tests;

import com.jayway.android.robotium.solo.Condition;
import @ANDROID_PACKAGE_NAME@.*;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.TabWidget;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;

import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * 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 BaseTest {
    protected enum AboutHomeTabs {HISTORY, MOST_RECENT, TABS_FROM_LAST_TIME, TOP_SITES, BOOKMARKS, READING_LIST};
    private ArrayList<String> aboutHomeTabs = new ArrayList<String>() {{
                  add("TOP_SITES");
                  add("BOOKMARKS");
                  add("READING_LIST");
              }};


    @Override
    protected 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 boolean isBookmarkDisplayed(String url) {
        View bookmark = getDisplayedBookmark(url);
        if (bookmark != null) {
            return true;
        } else {
            return false;
        }
    }

    // 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 ookmarked");
        }
    }

    // Opens the bookmark context menu by long-tapping on it
    protected void openBookmarkContextMenu(String url) {
        View bookmark = getDisplayedBookmark(url);
        if (bookmark != null) {
            mSolo.clickLongOnView(bookmark);
            waitForText("Share");
        } 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);
        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 ssues
                                  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;
    }

   /**
    * FIXME: rewrite this to work with fig when rewriting the testBookmarksTab test
    * This method will edit the bookmark with index = bookmarkIndex from the list of bookmarks
    * For the field index:
    *     fieldIndex = 1 - the Bookmark name
    *     fieldIndex = 2 - the Bookmark url
    *     fieldIndex = 3 - the Bookmark keyword
    */
    protected void editBookmark(int bookmarkIndex, int fieldIndex, String addedText, ListView list) {

        // Open the Edit Bookmark context menu
        View child;
        mSolo.clickOnText("Bookmarks");
        child = list.getChildAt(bookmarkIndex);
        mAsserter.ok(child != null, "edit item can be retrieved", child != null ? child.toString() : "null!");
        waitForText("Switch to tab");
        mSolo.clickLongOnView(child);
        waitForText("Share");
        mSolo.clickOnText("Edit");
        waitForText("Edit Bookmark");

        // Clear the Field
        mSolo.clearEditText(fieldIndex);

        // Enter the new text
        mSolo.clickOnEditText(fieldIndex);
        mActions.sendKeys(addedText);
        mSolo.clickOnText("OK");
        waitForText("Bookmark updated");
    }

    // FIXME: rewrite this to work with fig when rewriting the testBookmarksTab test
    protected boolean checkBookmarkEdit(int bookmarkIndex, String addedText, ListView list) {
        // Open the Edit Bookmark context menu
        View child;
        mSolo.clickOnText("Bookmarks");
        child = list.getChildAt(bookmarkIndex);
        mAsserter.ok(child != null, "check item can be retrieved", child != null ? child.toString() : "null!");
        waitForText("Switch to tab");
        mSolo.clickLongOnView(child);
        waitForText("Share");
        mSolo.clickOnText("Edit");
        waitForText("Edit Bookmark");

        // Check if the new text was added
        if (mSolo.searchText(addedText)) {
            clickOnButton("Cancel");
            waitForText("about:home");
            return true;
        } else {
            clickOnButton("Cancel");
            waitForText("about:home");
            return false;
        }
    }

    // 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);

        // Handle tablets by just clicking the visible tab title.
        if (mDevice.type.equals("tablet")) {
            // Just click for tablets, since all the titles are visible.
            if (AboutHomeTabs.MOST_RECENT == tab || AboutHomeTabs.TABS_FROM_LAST_TIME == tab) {
                mSolo.clickOnText(AboutHomeTabs.HISTORY.toString());
                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).
        final int currentTabIndex = pager.getCurrentItem();
        int 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;
            }

        }
    }
}