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