diff -r 000000000000 -r 6474c204b198 mobile/android/base/tests/testShareLink.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mobile/android/base/tests/testShareLink.java Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,264 @@ +package org.mozilla.gecko.tests; + +import java.util.ArrayList; +import java.util.List; + +import org.mozilla.gecko.Actions; + +import android.app.Activity; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Build; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.GridView; +import android.widget.ListView; +import android.widget.TextView; + +import com.jayway.android.robotium.solo.Condition; + +/** + * This test covers the opening and content of the Share Link pop-up list + * The test opens the Share menu from the app menu, the URL bar, a link context menu and the Awesomescreen tabs + */ +public class testShareLink extends AboutHomeTest { + String url; + String urlTitle = "Big Link"; + + public void testShareLink() { + url = getAbsoluteUrl("/robocop/robocop_big_link.html"); + ArrayList shareOptions; + blockForGeckoReady(); + + // FIXME: This is a temporary hack workaround for a permissions problem. + openAboutHomeTab(AboutHomeTabs.READING_LIST); + + inputAndLoadUrl(url); + verifyPageTitle(urlTitle); // Waiting for page title to ensure the page is loaded + + selectMenuItem("Share"); + if (Build.VERSION.SDK_INT >= 14) { + // Check for our own sync in the submenu. + waitForText("Sync$"); + } else { + waitForText("Share via"); + } + + // Get list of current avaliable share activities and verify them + shareOptions = getShareOptions(); + ArrayList displayedOptions = getShareOptionsList(); + for (String option:shareOptions) { + // Verify if the option is present in the list of displayed share options + mAsserter.ok(optionDisplayed(option, displayedOptions), "Share option found", option); + } + + // Test share from the urlbar context menu + mActions.sendSpecialKey(Actions.SpecialKey.BACK); // Close the share menu + mSolo.clickLongOnText(urlTitle); + verifySharePopup(shareOptions,"urlbar"); + + // The link has a 60px height, so let's try to hit the middle + float top = mDriver.getGeckoTop() + 30 * mDevice.density; + float left = mDriver.getGeckoLeft() + mDriver.getGeckoWidth() / 2; + mSolo.clickLongOnScreen(left, top); + verifySharePopup("Share Link",shareOptions,"Link"); + + // Test the share popup in the Bookmarks page + openAboutHomeTab(AboutHomeTabs.BOOKMARKS); + + final ListView bookmarksList = findListViewWithTag("bookmarks"); + mAsserter.is(waitForNonEmptyListToLoad(bookmarksList), true, "list is properly loaded"); + + int headerViewsCount = bookmarksList.getHeaderViewsCount(); + View bookmarksItem = bookmarksList.getChildAt(headerViewsCount); + if (bookmarksItem == null) { + mAsserter.dumpLog("no child at index " + headerViewsCount + "; waiting for one..."); + Condition listWaitCondition = new Condition() { + @Override + public boolean isSatisfied() { + if (bookmarksList.getChildAt(bookmarksList.getHeaderViewsCount()) == null) + return false; + return true; + } + }; + waitForCondition(listWaitCondition, MAX_WAIT_MS); + headerViewsCount = bookmarksList.getHeaderViewsCount(); + bookmarksItem = bookmarksList.getChildAt(headerViewsCount); + } + + mSolo.clickLongOnView(bookmarksItem); + verifySharePopup(shareOptions,"bookmarks"); + + // Prepopulate top sites with history items to overflow tiles. + // We are trying to move away from using reflection and doing more black-box testing. + inputAndLoadUrl(getAbsoluteUrl("/robocop/robocop_blank_01.html")); + inputAndLoadUrl(getAbsoluteUrl("/robocop/robocop_blank_02.html")); + inputAndLoadUrl(getAbsoluteUrl("/robocop/robocop_blank_03.html")); + inputAndLoadUrl(getAbsoluteUrl("/robocop/robocop_blank_04.html")); + if (mDevice.type.equals("tablet")) { + // Tablets have more tile spaces to fill. + inputAndLoadUrl(getAbsoluteUrl("/robocop/robocop_blank_05.html")); + inputAndLoadUrl(getAbsoluteUrl("/robocop/robocop_boxes.html")); + inputAndLoadUrl(getAbsoluteUrl("/robocop/robocop_search.html")); + inputAndLoadUrl(getAbsoluteUrl("/robocop/robocop_text_page.html")); + } + + // Test the share popup in Top Sites. + openAboutHomeTab(AboutHomeTabs.TOP_SITES); + + // Scroll down a bit so that the top sites list has more items on screen. + int width = mDriver.getGeckoWidth(); + int height = mDriver.getGeckoHeight(); + mActions.drag(width / 2, width / 2, height - 10, height / 2); + + ListView topSitesList = findListViewWithTag("top_sites"); + mAsserter.is(waitForNonEmptyListToLoad(topSitesList), true, "list is properly loaded"); + View mostVisitedItem = topSitesList.getChildAt(topSitesList.getHeaderViewsCount()); + mSolo.clickLongOnView(mostVisitedItem); + verifySharePopup(shareOptions,"top_sites"); + + // Test the share popup in the Most Recent tab + openAboutHomeTab(AboutHomeTabs.MOST_RECENT); + + ListView mostRecentList = findListViewWithTag("most_recent"); + mAsserter.is(waitForNonEmptyListToLoad(mostRecentList), true, "list is properly loaded"); + + // Getting second child after header views because the first is the "Today" label + View mostRecentItem = mostRecentList.getChildAt(mostRecentList.getHeaderViewsCount() + 1); + mSolo.clickLongOnView(mostRecentItem); + verifySharePopup(shareOptions,"most recent"); + } + + public void verifySharePopup(ArrayList shareOptions, String openedFrom) { + verifySharePopup("Share", shareOptions, openedFrom); + } + + public void verifySharePopup(String shareItemText, ArrayList shareOptions, String openedFrom) { + waitForText(shareItemText); + mSolo.clickOnText(shareItemText); + waitForText("Share via"); + ArrayList displayedOptions = getSharePopupOption(); + for (String option:shareOptions) { + // Verify if the option is present in the list of displayed share options + mAsserter.ok(optionDisplayed(option, displayedOptions), "Share option for " + openedFrom + (openedFrom.equals("urlbar") ? "" : " item") + " found", option); + } + mActions.sendSpecialKey(Actions.SpecialKey.BACK); + /** + * Adding a wait for the page title to make sure the Awesomebar will be dismissed + * Because of Bug 712370 the Awesomescreen will be dismissed when the Share Menu is closed + * so there is no need for handeling this different depending on where the share menu was invoced from + * TODO: Look more into why the delay is needed here now and it was working before + */ + waitForText(urlTitle); + } + + // Create a SEND intent and get the possible activities offered + public ArrayList getShareOptions() { + ArrayList shareOptions = new ArrayList(); + Activity currentActivity = getActivity(); + final Intent shareIntent = new Intent(Intent.ACTION_SEND); + shareIntent.putExtra(Intent.EXTRA_TEXT, url); + shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Robocop Blank 01"); + shareIntent.setType("text/plain"); + PackageManager pm = currentActivity.getPackageManager(); + List activities = pm.queryIntentActivities(shareIntent, 0); + for (ResolveInfo activity : activities) { + shareOptions.add(activity.loadLabel(pm).toString()); + } + return shareOptions; + } + + // Traverse the group of views, adding strings from TextViews to the list. + private void getGroupTextViews(ViewGroup group, ArrayList list) { + for (int i = 0; i < group.getChildCount(); i++) { + View child = group.getChildAt(i); + if (child instanceof AbsListView) { + getGroupTextViews((AbsListView)child, list); + } else if (child instanceof ViewGroup) { + getGroupTextViews((ViewGroup)child, list); + } else if (child instanceof TextView) { + String viewText = ((TextView)child).getText().toString(); + if (viewText != null && viewText.length() > 0) { + list.add(viewText); + } + } + } + } + + // Traverse the group of views, adding strings from TextViews to the list. + // This override is for AbsListView, which has adapters. If adapters are + // available, it is better to use them so that child views that are not + // yet displayed can be examined. + private void getGroupTextViews(AbsListView group, ArrayList list) { + for (int i = 0; i < group.getAdapter().getCount(); i++) { + View child = group.getAdapter().getView(i, null, group); + if (child instanceof AbsListView) { + getGroupTextViews((AbsListView)child, list); + } else if (child instanceof ViewGroup) { + getGroupTextViews((ViewGroup)child, list); + } else if (child instanceof TextView) { + String viewText = ((TextView)child).getText().toString(); + if (viewText != null && viewText.length() > 0) { + list.add(viewText); + } + } + } + } + + public ArrayList getSharePopupOption() { + ArrayList displayedOptions = new ArrayList(); + AbsListView shareMenu = getDisplayedShareList(); + getGroupTextViews(shareMenu, displayedOptions); + return displayedOptions; + } + + public ArrayList getShareSubMenuOption() { + ArrayList displayedOptions = new ArrayList(); + AbsListView shareMenu = getDisplayedShareList(); + getGroupTextViews(shareMenu, displayedOptions); + return displayedOptions; + } + + public ArrayList getShareOptionsList() { + if (Build.VERSION.SDK_INT >= 14) { + return getShareSubMenuOption(); + } else { + return getSharePopupOption(); + } + } + + private boolean optionDisplayed(String shareOption, ArrayList displayedOptions) { + for (String displayedOption: displayedOptions) { + if (shareOption.equals(displayedOption)) { + return true; + } + } + return false; + } + + private AbsListView mViewGroup; + + private AbsListView getDisplayedShareList() { + mViewGroup = null; + boolean success = waitForTest(new BooleanTest() { + @Override + public boolean test() { + ArrayList views = mSolo.getCurrentViews(); + for (View view : views) { + // List may be displayed in different view formats. + // On JB, GridView is common; on ICS-, ListView is common. + if (view instanceof ListView || + view instanceof GridView) { + mViewGroup = (AbsListView)view; + return true; + } + } + return false; + } + }, MAX_WAIT_MS); + mAsserter.ok(success,"Got the displayed share options?", "Got the share options view"); + return mViewGroup; + } +}