diff options
author | Kevin Jin <kjin@google.com> | 2014-03-28 19:02:21 -0700 |
---|---|---|
committer | Kevin Jin <kjin@google.com> | 2014-03-31 11:17:19 -0700 |
commit | df66b27599d3679de93f14ef972a32100d231683 (patch) | |
tree | 4ef686c02cc484f6264122897696a282385e7186 /src | |
parent | c91a011bd95b776da769c27e18cfd5b85a818491 (diff) | |
download | droiddriver-df66b27599d3679de93f14ef972a32100d231683.tar.gz |
add two new scroll APIs
ForwardingScrollStepStrategy and NullAccessibilityEventScrollStepStrategy
Change-Id: I16efb179f35d3fc178801c596a1d896c8b1e7644
Diffstat (limited to 'src')
3 files changed, 135 insertions, 12 deletions
diff --git a/src/com/google/android/droiddriver/helpers/PollingListeners.java b/src/com/google/android/droiddriver/helpers/PollingListeners.java index 2180264..44cd826 100644 --- a/src/com/google/android/droiddriver/helpers/PollingListeners.java +++ b/src/com/google/android/droiddriver/helpers/PollingListeners.java @@ -2,6 +2,7 @@ package com.google.android.droiddriver.helpers; import com.google.android.droiddriver.DroidDriver; import com.google.android.droiddriver.Poller.PollingListener; +import com.google.android.droiddriver.exceptions.ElementNotFoundException; import com.google.android.droiddriver.finders.Finder; /** @@ -15,11 +16,12 @@ public class PollingListeners { * @return whether {@code watchFinder} is found */ public static boolean tryFindAndClick(DroidDriver driver, Finder watchFinder) { - if (driver.has(watchFinder)) { + try { driver.find(watchFinder).click(); return true; + } catch (ElementNotFoundException enfe) { + return false; } - return false; } /** diff --git a/src/com/google/android/droiddriver/scroll/AccessibilityEventScrollStepStrategy.java b/src/com/google/android/droiddriver/scroll/AccessibilityEventScrollStepStrategy.java index 5e3d766..5b8f0f3 100644 --- a/src/com/google/android/droiddriver/scroll/AccessibilityEventScrollStepStrategy.java +++ b/src/com/google/android/droiddriver/scroll/AccessibilityEventScrollStepStrategy.java @@ -68,8 +68,8 @@ public class AccessibilityEventScrollStepStrategy implements ScrollStepStrategy } /** - * This filter allows us to grab the last accessibility event generated - * for a scroll up to {@code scrollEventTimeoutMillis}. + * This filter allows us to grab the last accessibility event generated for a + * scroll up to {@code scrollEventTimeoutMillis}. */ private static class LastScrollEventFilter implements AccessibilityEventFilter { private AccessibilityEvent lastEvent; @@ -83,7 +83,8 @@ public class AccessibilityEventScrollStepStrategy implements ScrollStepStrategy } lastEvent = AccessibilityEvent.obtain(event); } - // Return false to collect events until scrollEventTimeoutMillis has elapsed. + // Return false to collect events until scrollEventTimeoutMillis has + // elapsed. return false; } @@ -134,17 +135,21 @@ public class AccessibilityEventScrollStepStrategy implements ScrollStepStrategy if (event == null) { return true; } - boolean foundEnd = false; + if (event.getFromIndex() != -1 && event.getToIndex() != -1 && event.getItemCount() != -1) { - foundEnd = event.getFromIndex() == 0 || (event.getItemCount() - 1) == event.getToIndex(); - } else if (event.getScrollX() != -1 && event.getScrollY() != -1) { + return event.getFromIndex() == 0 || (event.getItemCount() - 1) == event.getToIndex(); + } + if (event.getScrollX() != -1 && event.getScrollY() != -1) { if (axis == Axis.VERTICAL) { - foundEnd = event.getScrollY() == 0 || event.getScrollY() == event.getMaxScrollY(); + return event.getScrollY() == 0 || event.getScrollY() == event.getMaxScrollY(); } else if (axis == Axis.HORIZONTAL) { - foundEnd = event.getScrollX() == 0 || event.getScrollX() == event.getMaxScrollX(); + return event.getScrollX() == 0 || event.getScrollX() == event.getMaxScrollX(); } } - return foundEnd; + + // This case is different from UiAutomator. + return event.getFromIndex() == -1 && event.getToIndex() == -1 && event.getItemCount() == -1 + && event.getScrollX() == -1 && event.getScrollY() == -1; } @Override @@ -181,7 +186,8 @@ public class AccessibilityEventScrollStepStrategy implements ScrollStepStrategy } catch (IllegalStateException e) { throw new UnrecoverableException(e); } catch (TimeoutException e) { - // We expect this because LastScrollEventFilter.accept always returns false. + // We expect this because LastScrollEventFilter.accept always returns + // false. } return filter.getLastEvent(); } @@ -190,4 +196,23 @@ public class AccessibilityEventScrollStepStrategy implements ScrollStepStrategy public void doScroll(final UiElement container, final PhysicalDirection direction) { SwipeAction.toScroll(direction).perform(container.getInjector(), container); } + + /** + * Some widgets may not always fire correct {@link AccessibilityEvent}. + * Detecting end by null event is safer (at the cost of a extra scroll) than + * examining indices. + */ + public static class NullAccessibilityEventScrollStepStrategy extends + AccessibilityEventScrollStepStrategy { + + public NullAccessibilityEventScrollStepStrategy(UiAutomation uiAutomation, + long scrollEventTimeoutMillis, DirectionConverter converter) { + super(uiAutomation, scrollEventTimeoutMillis, converter); + } + + @Override + protected boolean detectEnd(AccessibilityEvent event, Axis axis) { + return event == null; + } + } } diff --git a/src/com/google/android/droiddriver/scroll/ForwardingScrollStepStrategy.java b/src/com/google/android/droiddriver/scroll/ForwardingScrollStepStrategy.java new file mode 100644 index 0000000..7c849a5 --- /dev/null +++ b/src/com/google/android/droiddriver/scroll/ForwardingScrollStepStrategy.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2013 DroidDriver committers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.droiddriver.scroll; + +import android.widget.ProgressBar; + +import com.google.android.droiddriver.DroidDriver; +import com.google.android.droiddriver.UiElement; +import com.google.android.droiddriver.finders.By; +import com.google.android.droiddriver.finders.Finder; +import com.google.android.droiddriver.scroll.Direction.DirectionConverter; +import com.google.android.droiddriver.scroll.Direction.PhysicalDirection; + +/** + * An abstract base class for implementing the <a + * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>, + * forwarding calls to all methods of {@link ScrollStepStrategy} to delegate. + */ +public abstract class ForwardingScrollStepStrategy implements ScrollStepStrategy { + + protected ForwardingScrollStepStrategy() {} + + /** + * Returns the backing delegate instance that methods are forwarded to. + */ + protected abstract ScrollStepStrategy delegate(); + + public boolean scroll(DroidDriver driver, Finder containerFinder, PhysicalDirection direction) { + return delegate().scroll(driver, containerFinder, direction); + } + + @Override + public final DirectionConverter getDirectionConverter() { + return delegate().getDirectionConverter(); + } + + @Override + public void beginScrolling(DroidDriver driver, Finder containerFinder, Finder itemFinder, + PhysicalDirection direction) { + delegate().beginScrolling(driver, containerFinder, itemFinder, direction); + } + + @Override + public void endScrolling(DroidDriver driver, Finder containerFinder, Finder itemFinder, + PhysicalDirection direction) { + delegate().endScrolling(driver, containerFinder, itemFinder, direction); + } + + @Override + public void doScroll(UiElement container, PhysicalDirection direction) { + delegate().doScroll(container, direction); + } + + @Override + public String toString() { + return delegate().toString(); + } + + /** + * Augments the delegate {@link ScrollStepStrategy) - after a successful + * scroll, waits until ProgressBar is gone. + */ + public static abstract class ProgressBarScrollStepStrategy extends ForwardingScrollStepStrategy { + @Override + public boolean scroll(DroidDriver driver, Finder containerFinder, PhysicalDirection direction) { + if (super.scroll(driver, containerFinder, direction)) { + driver.checkGone(By.className(ProgressBar.class)); + return true; + } + return false; + } + + /** Convenience method to wrap {@code delegate} with this class */ + public static ScrollStepStrategy wrap(final ScrollStepStrategy delegate) { + return new ProgressBarScrollStepStrategy() { + @Override + protected ScrollStepStrategy delegate() { + return delegate; + } + }; + } + } +} |