Bug 1348086 - Part 3 - Port selectTabAt() to TabsPanelComponent. r?gbrown draft
authorJan Henning <jh+bugzilla@buttercookie.de>
Sat, 18 Mar 2017 20:19:01 +0100
changeset 503107 29fe74b8e05906f9d3f214fd4a5cec02c4d8c9e9
parent 503088 c2de34d14d09a3d92d5edc91aa9e422dab81f549
child 503108 422ee95de18a8bb510b8b2fbc3d49b4d268bbfdf
push id50503
push usermozilla@buttercookie.de
push dateWed, 22 Mar 2017 21:30:04 +0000
reviewersgbrown
bugs1348086
milestone55.0a1
Bug 1348086 - Part 3 - Port selectTabAt() to TabsPanelComponent. r?gbrown MozReview-Commit-ID: LlrgFq49Kyz
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITest.java
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITestContext.java
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/TabsPanelComponent.java
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITest.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITest.java
@@ -2,16 +2,17 @@
  * 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 org.mozilla.gecko.Actions;
 import org.mozilla.gecko.Assert;
 import org.mozilla.gecko.Driver;
+import org.mozilla.gecko.RobocopUtils;
 import org.mozilla.gecko.tests.components.AboutHomeComponent;
 import org.mozilla.gecko.tests.components.AppMenuComponent;
 import org.mozilla.gecko.tests.components.BaseComponent;
 import org.mozilla.gecko.tests.components.GeckoViewComponent;
 import org.mozilla.gecko.tests.components.TabStripComponent;
 import org.mozilla.gecko.tests.components.TabsPanelComponent;
 import org.mozilla.gecko.tests.components.ToolbarComponent;
 import org.mozilla.gecko.tests.helpers.HelperInitializer;
@@ -144,16 +145,21 @@ abstract class UITest extends BaseRoboco
     private String getAbsoluteUrl(final String baseUrl, final String url) {
         if (!url.startsWith(baseUrl)) {
             return baseUrl + "/" + url.replaceAll("(^/)", "");
         }
 
         return url;
     }
 
+    @Override
+    public final void runOnUiThreadSync(Runnable runnable) {
+        RobocopUtils.runOnUiThreadSync(getActivity(), runnable);
+    }
+
     /**
      * Throws an Exception. Called from overridden JUnit methods to ensure JUnit assertions
      * are not accidentally used over AssertionHelper assertions (the latter of which contains
      * additional logging facilities for use in our test harnesses).
      */
     private static void junit() {
         throw new UnsupportedOperationException(JUNIT_FAILURE_MSG);
     }
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITestContext.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITestContext.java
@@ -42,10 +42,12 @@ public interface UITestContext {
      */
     public String getAbsoluteHostnameUrl(final String url);
 
     /**
      * Returns the absolute version of the given URL using the host's IP address.
      */
     public String getAbsoluteIpUrl(final String url);
 
+    public void runOnUiThreadSync(Runnable runnable);
+
     public BaseComponent getComponent(final ComponentType type);
 }
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/TabsPanelComponent.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/TabsPanelComponent.java
@@ -10,16 +10,18 @@ import org.mozilla.gecko.tabs.TabsLayout
 import org.mozilla.gecko.tests.UITestContext;
 import org.mozilla.gecko.tests.helpers.WaitHelper;
 
 import java.util.List;
 
 import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue;
 
 public class TabsPanelComponent extends TabsPresenterComponent {
+    private static final int MAX_WAIT_MS = 4500;
+
     public TabsPanelComponent(final UITestContext testContext) {
         super(testContext);
     }
 
     public void openPanel() {
         assertTabsPanelIsClosed();
         mSolo.clickOnView(mSolo.getView(R.id.tabs));
         WaitHelper.waitFor("tabs panel to open", new Condition() {
@@ -86,9 +88,68 @@ public class TabsPanelComponent extends 
         final View tabsPanel = getTabsPanel();
         fAssertTrue("Tabs panel is open", tabsPanel != null && tabsPanel.getVisibility() == View.VISIBLE);
     }
 
     private void assertTabsPanelIsClosed() {
         final View tabsPanel = getTabsPanel();
         fAssertTrue("Tabs panel is closed", tabsPanel == null || tabsPanel.getVisibility() != View.VISIBLE);
     }
+
+    /**
+     * Scrolls the tabs panel and then selects the tab at the specified index.
+     *
+     * @param index Index of tab to select
+     */
+    public void selectTabAt(final int index) {
+        mSolo.clickOnView(scrollAndGetTabViewAt(index));
+    }
+
+    /**
+     * Gets the view in the tabs panel at the specified index.
+     *
+     * @return View at index
+     */
+    private View scrollAndGetTabViewAt(final int index) {
+        final View[] childView = { null };
+
+        final RecyclerView view = getTabsLayout();
+
+        mTestContext.runOnUiThreadSync(new Runnable() {
+            @Override
+            public void run() {
+                view.scrollToPosition(index);
+
+                // The selection isn't updated synchronously; posting a
+                // runnable to the view's queue guarantees we'll run after the
+                // layout pass.
+                view.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        // Index is relative to all views in the list.
+                        final RecyclerView.ViewHolder itemViewHolder =
+                                view.findViewHolderForLayoutPosition(index);
+                        childView[0] = itemViewHolder == null ? null : itemViewHolder.itemView;
+                    }
+                });
+            }
+        });
+
+        WaitHelper.waitFor("list item at index " + index + " exists", new Condition() {
+            @Override
+            public boolean isSatisfied() {
+                return childView[0] != null;
+            }
+        }, MAX_WAIT_MS);
+
+        return childView[0];
+    }
+
+    /**
+     * Gets the RecyclerView of the tabs list.
+     *
+     * @return List view in the tabs panel
+     */
+    private RecyclerView getTabsLayout() {
+        openPanel();
+        return (RecyclerView) mSolo.getView(R.id.normal_tabs);
+    }
 }