/** * Scrolls up and down. * * @param direction the direction in which to scroll * @param allTheWay <code>true</code> if the view should be scrolled to the beginning or end, * <code>false</code> to scroll one page up or down. * @return {@code true} if more scrolling can be done */ public boolean scroll(int direction, boolean allTheWay) { final ArrayList<View> viewList = RobotiumUtils.removeInvisibleViews(viewFetcher.getAllViews(true)); @SuppressWarnings("unchecked") ArrayList<View> views = RobotiumUtils.filterViewsToSet( new Class[] {ListView.class, ScrollView.class, GridView.class, WebView.class}, viewList); View view = viewFetcher.getFreshestView(views); if (view == null) { view = viewFetcher.getRecyclerView(0); if (view == null) { return false; } } if (view instanceof AbsListView) { return scrollList((AbsListView) view, direction, allTheWay); } if (view instanceof WebView) { return scrollWebView((WebView) view, direction, allTheWay); } if (allTheWay) { scrollViewAllTheWay(view, direction); return false; } else { return scrollView(view, direction); } }
/** Extract and wrap the all OpenGL ES Renderer. */ private void wrapAllGLViews(View decorView) { ArrayList<GLSurfaceView> currentViews = viewFetcher.getCurrentViews(GLSurfaceView.class, true, decorView); final CountDownLatch latch = new CountDownLatch(currentViews.size()); for (GLSurfaceView glView : currentViews) { Object renderContainer = new Reflect(glView).field("mGLThread").type(GLSurfaceView.class).out(Object.class); Renderer renderer = new Reflect(renderContainer).field("mRenderer").out(Renderer.class); if (renderer == null) { renderer = new Reflect(glView).field("mRenderer").out(Renderer.class); renderContainer = glView; } if (renderer == null) { latch.countDown(); continue; } if (renderer instanceof GLRenderWrapper) { GLRenderWrapper wrapper = (GLRenderWrapper) renderer; wrapper.setTakeScreenshot(); wrapper.setLatch(latch); } else { GLRenderWrapper wrapper = new GLRenderWrapper(glView, renderer, latch); new Reflect(renderContainer).field("mRenderer").in(wrapper); } } try { latch.await(); } catch (InterruptedException ex) { ex.printStackTrace(); } }
/** * Waits for and returns a View. * * @param index the index of the view * @param classToFilterby the class to filter * @return the specified View */ public <T extends View> T waitForAndGetView(int index, Class<T> classToFilterBy) { long endTime = SystemClock.uptimeMillis() + Timeout.getSmallTimeout(); while (SystemClock.uptimeMillis() <= endTime && !waitForView(classToFilterBy, index, true, true)) ; int numberOfUniqueViews = searcher.getNumberOfUniqueViews(); ArrayList<T> views = RobotiumUtils.removeInvisibleViews(viewFetcher.getCurrentViews(classToFilterBy)); if (views.size() < numberOfUniqueViews) { int newIndex = index - (numberOfUniqueViews - views.size()); if (newIndex >= 0) index = newIndex; } T view = null; try { view = views.get(index); } catch (IndexOutOfBoundsException exception) { int match = index + 1; if (match > 1) { Assert.fail(match + " " + classToFilterBy.getSimpleName() + "s" + " are not found!"); } else { Assert.fail(classToFilterBy.getSimpleName() + " is not found!"); } } views = null; return view; }
/** * Waits for a given view. * * @param view the view to wait for * @param timeout the amount of time in milliseconds to wait * @param scroll {@code true} if scrolling should be performed * @param checkIsShown {@code true} if view.isShown() should be used * @return {@code true} if view is shown and {@code false} if it is not shown before the timeout */ public View waitForView(View view, int timeout, boolean scroll, boolean checkIsShown) { long endTime = SystemClock.uptimeMillis() + timeout; int retry = 0; if (view == null) return null; while (SystemClock.uptimeMillis() < endTime) { final boolean foundAnyMatchingView = searcher.searchFor(view); if (checkIsShown && foundAnyMatchingView && !view.isShown()) { sleeper.sleepMini(); retry++; View identicalView = viewFetcher.getIdenticalView(view); if (identicalView != null && !view.equals(identicalView)) { view = identicalView; } if (retry > 5) { return view; } continue; } if (foundAnyMatchingView) { return view; } if (scroll) scroller.scrollDown(); sleeper.sleep(); } return view; }
/** * Checks if a given text is selected in any {@link Spinner} located on the current screen. * * @param text the text that is expected to be selected * @return {@code true} if the given text is selected in any {@code Spinner} and false if it is * not */ public boolean isSpinnerTextSelected(String text) { waiter.waitForView(Spinner.class, 0); ArrayList<Spinner> spinnerList = viewFetcher.getCurrentViews(Spinner.class); for (int i = 0; i < spinnerList.size(); i++) { if (isSpinnerTextSelected(i, text)) return true; } return false; }
/** * Checks if a {@link CheckedTextView} with a given text is checked. * * @param checkedTextView the {@code CheckedTextView} object * @param text the text that is expected to be checked * @return {@code true} if {@code CheckedTextView} is checked and {@code false} if it is not * checked */ public boolean isCheckedTextChecked(String text) { waiter.waitForText(text, 0, 10000, true, true); ArrayList<CheckedTextView> list = viewFetcher.getCurrentViews(CheckedTextView.class); for (CheckedTextView checkedText : list) { if (checkedText.getText().equals(text) && checkedText.isChecked()) return true; } return false; }
/** * Checks if a {@link CompoundButton} with a given text is checked. * * @param expectedClass the expected class, e.g. {@code CheckBox.class} or {@code * RadioButton.class} * @param text the text that is expected to be checked * @return {@code true} if {@code CompoundButton} is checked and {@code false} if it is not * checked */ public <T extends CompoundButton> boolean isButtonChecked(Class<T> expectedClass, String text) { waiter.waitForView(expectedClass, 0); ArrayList<T> list = viewFetcher.getCurrentViews(expectedClass); for (T button : list) { if (button.getText().equals(text) && button.isChecked()) return true; } return false; }
/** Gets the proper view to use for a screenshot. */ private View getScreenshotView() { View decorView = viewFetcher.getRecentDecorView(viewFetcher.getWindowDecorViews()); final long endTime = SystemClock.uptimeMillis() + Timeout.getSmallTimeout(); while (decorView == null) { final boolean timedOut = SystemClock.uptimeMillis() > endTime; if (timedOut) { return null; } sleeper.sleepMini(); decorView = viewFetcher.getRecentDecorView(viewFetcher.getWindowDecorViews()); } wrapAllGLViews(decorView); return decorView; }
/** * Checks if a {@link CompoundButton} with a given index is checked. * * @param expectedClass the expected class, e.g. {@code CheckBox.class} or {@code * RadioButton.class} * @param index of the {@code CompoundButton} to check. {@code 0} if only one is available * @return {@code true} if {@code CompoundButton} is checked and {@code false} if it is not * checked */ public <T extends CompoundButton> boolean isButtonChecked(Class<T> expectedClass, int index) { waiter.waitForView(expectedClass, index, false); ArrayList<T> list = viewFetcher.getCurrentViews(expectedClass); list = RobotiumUtils.removeInvisibleViews(list); if (index < 0 || index > list.size() - 1) Assert.assertTrue( "No " + expectedClass.getSimpleName() + " with index " + index + " is found", false); return (list.get(index)).isChecked(); }
/** * Checks if a given text is selected in a given {@link Spinner} * * @param spinnerIndex the index of the spinner to check. 0 if only one spinner is available * @param text the text that is expected to be selected * @return true if the given text is selected in the given {@code Spinner} and false if it is not */ public boolean isSpinnerTextSelected(int spinnerIndex, String text) { waiter.waitForView(Spinner.class, spinnerIndex, false); ArrayList<Spinner> spinnerList = viewFetcher.getCurrentViews(Spinner.class); if (spinnerList.size() < spinnerIndex + 1) Assert.assertTrue("No spinner with index " + spinnerIndex + " is found! ", false); Spinner spinner = spinnerList.get(spinnerIndex); TextView textView = (TextView) spinner.getChildAt(spinner.getSelectedItemPosition()); if (textView.getText().equals(text)) return true; else return false; }
/** * Waits for a certain view. * * @param view the id of the view to wait for * @param index the index of the {@link View}. {@code 0} if only one is available * @return the specified View */ public View waitForView(int id, int index, int timeout, boolean scroll) { Set<View> uniqueViewsMatchingId = new HashSet<View>(); long endTime = SystemClock.uptimeMillis() + timeout; while (SystemClock.uptimeMillis() <= endTime) { sleeper.sleep(); for (View view : viewFetcher.getAllViews(false)) { Integer idOfView = Integer.valueOf(view.getId()); if (idOfView.equals(id)) { uniqueViewsMatchingId.add(view); if (uniqueViewsMatchingId.size() > index) { return view; } } } if (scroll) scroller.scrollDown(); } return null; }