#filter substitution package @ANDROID_PACKAGE_NAME@.tests; import @ANDROID_PACKAGE_NAME@.*; import android.view.ViewGroup; import android.view.View; import android.widget.ListView; import android.widget.TextView; import android.widget.ImageView; import android.text.TextUtils; import android.content.ContentResolver; import android.net.Uri; import java.util.Arrays; import java.util.ArrayList; import java.util.Calendar; import java.util.GregorianCalendar; /* Tests opening the history tab, that items look correct, clicking on an item and long tapping on an item */ public class testHistoryTab extends PixelTest { private static final String ABOUT_HOME_URL = "about:home"; private static ListView listview = null; private String[] mBookmarks = new String[] { "Browser Blank Page 01", "Firefox: Customize with add-ons" }; private View mChild; private boolean mNearMidnight; @Override protected int getTestType() { return TEST_MOCHITEST; } public void testHistoryTab() { blockForGeckoReady(); // very approximate date-rollover detection Calendar cal = new GregorianCalendar(); mNearMidnight = (cal.get(Calendar.HOUR_OF_DAY) == 23); // load two pages so there is something in our history // bookmark one of them String url = getAbsoluteUrl("/robocop/robocop_big_link.html"); loadAndPaint(url); url = getAbsoluteUrl("/robocop/robocop_blank_01.html"); loadAndPaint(url); mActions.sendSpecialKey(Actions.SpecialKey.MENU); waitForText("Settings"); // On ICS+ phones, there is no button labeled "Bookmarks" // instead we have to just dig through every button on the screen ArrayList images = mSolo.getCurrentViews(); for (int i = 0; i < images.size(); i++) { final View view = images.get(i); boolean found = false; found = "Bookmark".equals(view.getContentDescription()); // on older android versions, try looking at the button's text if (!found) { if (view instanceof TextView) { found = "Bookmark".equals(((TextView)view).getText()); } } if (found) { int[] xy = new int[2]; view.getLocationOnScreen(xy); final int viewWidth = view.getWidth(); final int viewHeight = view.getHeight(); final float x = xy[0] + (viewWidth / 2.0f); float y = xy[1] + (viewHeight / 2.0f); mSolo.clickOnScreen(x, y); } } mAsserter.is(mSolo.waitForText("Bookmark added"), true, "bookmark added successfully"); testList(url); testContextMenu(url); testClick(getAbsoluteUrl("/robocop/robocop_big_link.html")); } private void testList(String url) { listview = getHistoryList("Today|Yesterday", 3); mAsserter.isnot(listview, null, "checking that history list exists and has 3 children"); final int count = listview.getAdapter().getCount(); String loadUrl = ""; for (int i = count - 1; i >= 0; i--) { View child = listview.getChildAt(i); if (child == null) { // this may simply indicate that the item is not visible Object item = listview.getAdapter().getItem(i); mAsserter.ok(item != null, "adapter item is set", item != null ? item.toString() : "null!"); continue; } ArrayList views = mSolo.getViews(child); ArrayList imageViews = new ArrayList(); int expectedImages = 1; for (int j = 0; j < views.size(); j++) { View v = views.get(j); // First row is going to be a header row if (i == 0) { ArrayList views2 = mSolo.getCurrentTextViews(v); TextView t = views2.get(0); String string = t.getText().toString(); boolean headerTextOK = string.equals("Today"); if (!headerTextOK && mNearMidnight && string.equals("Yesterday")) { headerTextOK = true; } mAsserter.ok(headerTextOK, "First row has Today header", string); expectedImages = 0; } else if (v instanceof TextView) { // if this is a textview, its either the title or the url. In either case, both should be filled in TextView t = (TextView)v; String string = t.getText().toString(); mAsserter.ok(!TextUtils.isEmpty(string), "TextView is filled in", string); if (i == 1 || string.startsWith("http")) { loadUrl = string; } // if this was a url, check if its a bookmark and should have more than one image view present if (isBookmark(mBookmarks, string)) { expectedImages = 2; } } else if (v instanceof ImageView) { imageViews.add((ImageView)v); } } int visible = 0; for (int j = 0; j < imageViews.size(); j++) { ImageView img = imageViews.get(j); visible += (img.getVisibility() == View.VISIBLE) ? 1 : 0; } mAsserter.is(visible, expectedImages, "Correct number of ImageViews visible"); } mActions.sendSpecialKey(Actions.SpecialKey.BACK); } private void testContextMenu(String url) { listview = getHistoryList("Today|Yesterday"); waitForText(url); // wait for the history list to be populated mChild = null; boolean success = waitForTest(new BooleanTest() { @Override public boolean test() { mChild = listview.getChildAt(1); if (mChild == null) { return false; } if (mChild instanceof android.view.ViewGroup) { ViewGroup group = (ViewGroup)mChild; if (group.getChildCount() < 1) { return false; } for (int i = 0; i < group.getChildCount(); i++) { View grandChild = group.getChildAt(i); if (grandChild instanceof android.widget.TextView) { mAsserter.ok(true, "found TextView:", ((android.widget.TextView)grandChild).getText().toString()); } } } else { mAsserter.dumpLog("first child not a ViewGroup: "+mChild); return false; } return true; } }, MAX_WAIT_MS); if (success == true && mChild != null) { mAsserter.dumpLog("clickLongOnView: "+mChild); mSolo.clickLongOnView(mChild); // TODO: Test clicking these does the right thing mAsserter.ok(mSolo.waitForText("Open in New Tab"), "Context menu has Open in New Tab option", "Open in New Tab"); mAsserter.ok(mSolo.waitForText("Share"), "Context menu has Share option", "Share"); mAsserter.ok(mSolo.searchText("Remove", true), "Context menu has Remove option", "Remove"); mAsserter.ok(mSolo.searchText("Add to Home Screen", true), "Context menu has Add to Home Screen option", "Add to Home Screen"); mActions.sendSpecialKey(Actions.SpecialKey.BACK); View child = listview.getChildAt(0); mAsserter.ok(child != null, "first list item can be retrieved", child != null ? child.toString() : "null!"); mSolo.clickLongOnView(child); mAsserter.is(false, mSolo.waitForText("Share"), "Header rows should not show a context menu"); } else { mAsserter.ok(false, "waiting for history item", "history item available"); } mActions.sendSpecialKey(Actions.SpecialKey.BACK); } private void testClick(String url) { listview = getHistoryList("Today|Yesterday"); waitForText(url); View child = listview.getChildAt(0); mAsserter.ok(child != null, "first list item can be retrieved", child != null ? child.toString() : "null!"); mSolo.clickOnView(child); // nothing should happen mChild = null; boolean success = waitForTest(new BooleanTest() { @Override public boolean test() { // Avoid clicking on the first entry, which is already open and will just switch to the tab mChild = listview.getChildAt(2); if (mChild == null) { return false; } return true; } }, MAX_WAIT_MS); if (success == true && mChild != null) { Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded"); mSolo.clickOnView(mChild); contentEventExpecter.blockForEvent(); contentEventExpecter.unregisterListener(); // TODO: Find a better way to wait for update before checking // awesome bar; lesser waits result in intermittent failures mSolo.sleep(2000); verifyUrl(url); } else { mAsserter.ok(false, "waiting for history item", "history item available"); } } @Override public void tearDown() throws Exception { ContentResolver resolver = getActivity().getContentResolver(); Uri uri = Uri.parse("content://@ANDROID_PACKAGE_NAME@.db.browser/history"); uri = uri.buildUpon().appendQueryParameter("profile", "default") .appendQueryParameter("sync", "true").build(); resolver.delete(uri, "url = ?", new String[] { "http://mochi.test:8888/tests/robocop/robocop_blank_01.html" }); resolver.delete(uri, "url = ?", new String[] { "http://mochi.test:8888/tests/robocop/robocop_big_link.html" }); uri = Uri.parse("content://@ANDROID_PACKAGE_NAME@.db.browser/bookmarks"); uri = uri.buildUpon().appendQueryParameter("profile", "default") .appendQueryParameter("sync", "true").build(); resolver.delete(uri, "url = ?", new String[] { "http://mochi.test:8888/tests/robocop/robocop_blank_01.html" }); super.tearDown(); } }