19c92f46280cf3943701e75349833c68b584992e2Kevin Jin/*
29c92f46280cf3943701e75349833c68b584992e2Kevin Jin * Copyright (C) 2013 DroidDriver committers
39c92f46280cf3943701e75349833c68b584992e2Kevin Jin *
49c92f46280cf3943701e75349833c68b584992e2Kevin Jin * Licensed under the Apache License, Version 2.0 (the "License");
59c92f46280cf3943701e75349833c68b584992e2Kevin Jin * you may not use this file except in compliance with the License.
69c92f46280cf3943701e75349833c68b584992e2Kevin Jin * You may obtain a copy of the License at
79c92f46280cf3943701e75349833c68b584992e2Kevin Jin *
89c92f46280cf3943701e75349833c68b584992e2Kevin Jin *      http://www.apache.org/licenses/LICENSE-2.0
99c92f46280cf3943701e75349833c68b584992e2Kevin Jin *
109c92f46280cf3943701e75349833c68b584992e2Kevin Jin * Unless required by applicable law or agreed to in writing, software
119c92f46280cf3943701e75349833c68b584992e2Kevin Jin * distributed under the License is distributed on an "AS IS" BASIS,
129c92f46280cf3943701e75349833c68b584992e2Kevin Jin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139c92f46280cf3943701e75349833c68b584992e2Kevin Jin * See the License for the specific language governing permissions and
149c92f46280cf3943701e75349833c68b584992e2Kevin Jin * limitations under the License.
159c92f46280cf3943701e75349833c68b584992e2Kevin Jin */
169c92f46280cf3943701e75349833c68b584992e2Kevin Jin
179c92f46280cf3943701e75349833c68b584992e2Kevin Jinpackage com.google.android.droiddriver.scroll;
189c92f46280cf3943701e75349833c68b584992e2Kevin Jin
199c92f46280cf3943701e75349833c68b584992e2Kevin Jinimport android.app.UiAutomation;
20d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jinimport android.widget.ProgressBar;
219c92f46280cf3943701e75349833c68b584992e2Kevin Jin
22d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jinimport com.google.android.droiddriver.DroidDriver;
23d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jinimport com.google.android.droiddriver.finders.By;
24d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jinimport com.google.android.droiddriver.finders.Finder;
25c39b04e0e5d3962153cd860d1430857fe625da90Kevin Jinimport com.google.android.droiddriver.scroll.Direction.Axis;
269c92f46280cf3943701e75349833c68b584992e2Kevin Jinimport com.google.android.droiddriver.scroll.Direction.DirectionConverter;
27d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jinimport com.google.android.droiddriver.scroll.Direction.PhysicalDirection;
289c92f46280cf3943701e75349833c68b584992e2Kevin Jin
299c92f46280cf3943701e75349833c68b584992e2Kevin Jin/**
30d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin * Static utility classes and methods pertaining to {@link Scroller} instances.
319c92f46280cf3943701e75349833c68b584992e2Kevin Jin */
329c92f46280cf3943701e75349833c68b584992e2Kevin Jinpublic class Scrollers {
339c92f46280cf3943701e75349833c68b584992e2Kevin Jin  /**
34d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin   * Augments the delegate {@link ScrollStepStrategy) - after a successful
35d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin   * scroll, waits until ProgressBar is gone.
36d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin   */
37d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin  public static abstract class ProgressBarScrollStepStrategy extends ForwardingScrollStepStrategy {
38d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin    @Override
39d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin    public boolean scroll(DroidDriver driver, Finder containerFinder, PhysicalDirection direction) {
40d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin      if (super.scroll(driver, containerFinder, direction)) {
41d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin        driver.checkGone(By.className(ProgressBar.class));
42d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin        return true;
43d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin      }
44d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin      return false;
45d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin    }
46d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin
47d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin    /** Convenience method to wrap {@code delegate} with this class */
48d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin    public static ScrollStepStrategy wrap(final ScrollStepStrategy delegate) {
49d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin      return new ProgressBarScrollStepStrategy() {
50d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin        @Override
51d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin        protected ScrollStepStrategy delegate() {
52d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin          return delegate;
53d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin        }
54d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin      };
55d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin    }
56d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin  }
57d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin
58d9ecc536e454bd4c23d6e0bbf5af1328e34b1748Kevin Jin  /**
599c92f46280cf3943701e75349833c68b584992e2Kevin Jin   * Returns a new default Scroller that works in simple cases. In complex cases
609c92f46280cf3943701e75349833c68b584992e2Kevin Jin   * you may try a {@link StepBasedScroller} with a custom
619c92f46280cf3943701e75349833c68b584992e2Kevin Jin   * {@link ScrollStepStrategy}:
629c92f46280cf3943701e75349833c68b584992e2Kevin Jin   * <ul>
639c92f46280cf3943701e75349833c68b584992e2Kevin Jin   * <li>If the Scroller is used with InstrumentationDriver,
649c92f46280cf3943701e75349833c68b584992e2Kevin Jin   * StaticSentinelStrategy may work and it's the simplest.</li>
659c92f46280cf3943701e75349833c68b584992e2Kevin Jin   * <li>Otherwise, DynamicSentinelStrategy should work in all cases, including
669c92f46280cf3943701e75349833c68b584992e2Kevin Jin   * the case of dynamic list, which shows more items when scrolling beyond the
679c92f46280cf3943701e75349833c68b584992e2Kevin Jin   * end. On the other hand, it's complex and needs more configuration.</li>
689c92f46280cf3943701e75349833c68b584992e2Kevin Jin   * </ul>
69c39b04e0e5d3962153cd860d1430857fe625da90Kevin Jin   * Note if a {@link StepBasedScroller} is returned, it is constructed with
70c39b04e0e5d3962153cd860d1430857fe625da90Kevin Jin   * arguments that apply to typical cases. You may want to customize them for
71c39b04e0e5d3962153cd860d1430857fe625da90Kevin Jin   * specific cases. For instance, {@code perScrollTimeoutMillis} can be 0L if
72c39b04e0e5d3962153cd860d1430857fe625da90Kevin Jin   * there are no asynchronously updated views. To that extent, this method
73a6749c6913f014416419850a9fb5235a745fdeb8Kevin Jin   * serves as an example of how to construct {@link Scroller}s rather than
74c39b04e0e5d3962153cd860d1430857fe625da90Kevin Jin   * providing the "official" {@link Scroller}.
759c92f46280cf3943701e75349833c68b584992e2Kevin Jin   */
769c92f46280cf3943701e75349833c68b584992e2Kevin Jin  public static Scroller newScroller(UiAutomation uiAutomation) {
779c92f46280cf3943701e75349833c68b584992e2Kevin Jin    if (uiAutomation != null) {
78c39b04e0e5d3962153cd860d1430857fe625da90Kevin Jin      return new StepBasedScroller(100/* maxScrolls */, 1000L/* perScrollTimeoutMillis */,
79c39b04e0e5d3962153cd860d1430857fe625da90Kevin Jin          Axis.VERTICAL, new AccessibilityEventScrollStepStrategy(uiAutomation, 1000L,
80c39b04e0e5d3962153cd860d1430857fe625da90Kevin Jin              DirectionConverter.STANDARD_CONVERTER), true/* startFromBeginning */);
819c92f46280cf3943701e75349833c68b584992e2Kevin Jin    }
829c92f46280cf3943701e75349833c68b584992e2Kevin Jin    // TODO: A {@link Scroller} that directly jumps to the view if an
839c92f46280cf3943701e75349833c68b584992e2Kevin Jin    // InstrumentationDriver is used.
84c39b04e0e5d3962153cd860d1430857fe625da90Kevin Jin    return new StepBasedScroller(100/* maxScrolls */, 1000L/* perScrollTimeoutMillis */,
85c39b04e0e5d3962153cd860d1430857fe625da90Kevin Jin        Axis.VERTICAL, StaticSentinelStrategy.DEFAULT, true/* startFromBeginning */);
869c92f46280cf3943701e75349833c68b584992e2Kevin Jin  }
879c92f46280cf3943701e75349833c68b584992e2Kevin Jin}
88