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