aboutsummaryrefslogtreecommitdiff
path: root/libs/UiAutomatorLib/src/com/android/afwtest/uiautomator/pages/PageSkipper.java
diff options
context:
space:
mode:
Diffstat (limited to 'libs/UiAutomatorLib/src/com/android/afwtest/uiautomator/pages/PageSkipper.java')
-rw-r--r--libs/UiAutomatorLib/src/com/android/afwtest/uiautomator/pages/PageSkipper.java233
1 files changed, 233 insertions, 0 deletions
diff --git a/libs/UiAutomatorLib/src/com/android/afwtest/uiautomator/pages/PageSkipper.java b/libs/UiAutomatorLib/src/com/android/afwtest/uiautomator/pages/PageSkipper.java
new file mode 100644
index 0000000..cc3c8c8
--- /dev/null
+++ b/libs/UiAutomatorLib/src/com/android/afwtest/uiautomator/pages/PageSkipper.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.android.afwtest.uiautomator.pages;
+
+import static com.android.afwtest.common.Constants.ACTION_CHECK;
+import static com.android.afwtest.common.Constants.ACTION_CLICK;
+import static com.android.afwtest.common.Constants.ACTION_SCROLL;
+import static com.android.afwtest.uiautomator.utils.WidgetUtils.safeClick;
+import static com.android.afwtest.uiautomator.utils.WidgetUtils.safeFling;
+
+import android.os.SystemClock;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.afwtest.common.Timer;
+import com.android.afwtest.common.test.OemWidget;
+import com.android.afwtest.common.test.TestConfig;
+import com.android.afwtest.uiautomator.utils.BySelectorHelper;
+import com.android.afwtest.uiautomator.utils.WidgetUtils;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+/**
+ * A help class to skip pages until the expected page appears.
+ */
+public final class PageSkipper extends UiPage {
+
+ private static final String TAG = "afwtest.PageSkipper";
+
+ /**
+ * Thread sleep time.
+ */
+ private static final long THREAD_SLEEP_TIME_MS = TimeUnit.SECONDS.toMillis(3);
+
+ /**
+ * Words to match when finding available "NEXT" navigation buttons.
+ *
+ * The order of the list is preferring skip over continue or next.
+ */
+ private static final String[] NEXT_WORDS = {
+ "[sS]kip", "SKIP",
+ "[fF]inish", "FINISH",
+ "[dD]one", "DONE",
+ "[nN]ext", "NEXT",
+ "[cC]ontinue", "CONTINUE",
+ "[pP]roceed", "PROCEED",
+ "[yY][eE][sS]", "[oO][kK]"};
+
+ /**
+ * {@link Pattern} to match for NEXT buttons.
+ */
+ private static final Pattern NEXT_BTN_PATTERN =
+ Pattern.compile(TextUtils.join("|", NEXT_WORDS));
+
+ /**
+ * Buttons with text matching {@link #NEXT_BTN_PATTERN}.
+ */
+ private static final BySelector NAVIGATION_BTN_TEXT_SELECTOR =
+ By.enabled(true)
+ .checkable(false)
+ .clickable(true)
+ .text(NEXT_BTN_PATTERN);
+
+ /**
+ * Buttons with content description matching {@link #NEXT_BTN_PATTERN}.
+ */
+ private static final BySelector NAVIGATION_BTN_DESC_SELECTOR =
+ By.enabled(true)
+ .checkable(false)
+ .clickable(true)
+ .desc(NEXT_BTN_PATTERN);
+
+ /**
+ * List of package names whose buttons should not be clicked.
+ */
+ private Set<String> mPackageNameBlacklist = null;
+
+ /**
+ * Stop skipping when any object with this {@link BySelector} is found.
+ */
+ private final BySelector mSkipEndSelector;
+
+ /**
+ * Creates a new page skipper.
+ *
+ * @param uiDevice {@link UiDevice} object to access UIAutomator API
+ * @param skipEndSelector stop skipping pages if this any object matching this
+ * {@link BySelector} is found
+ * @param testConfig {@link testConfig} to get test configurations
+ */
+ public PageSkipper(UiDevice uiDevice, BySelector skipEndSelector, TestConfig testConfig) {
+ super(uiDevice, testConfig);
+
+ mSkipEndSelector = skipEndSelector;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean waitForLoading() throws Exception {
+ // Do nothing.
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public BySelector uniqueElement() {
+ // No unique element.
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void navigate() throws Exception {
+ long timeout = TimeUnit.MINUTES.toMillis(1) * getTestConfig().getTimeoutSize();
+ Timer timer = new Timer(timeout);
+ List<OemWidget> oemWidgets = getTestConfig().getOemWidgets();
+ timer.start();
+ while (!timer.isTimeUp() && !getUiDevice().hasObject(mSkipEndSelector)) {
+
+ if (!clickAvailableNextButton()) {
+ iterateOemWidgets(oemWidgets);
+ }
+
+ // Assert on fatal app crash
+ assertOnFatalAppCrash();
+
+ SystemClock.sleep(THREAD_SLEEP_TIME_MS);
+ }
+
+ if (timer.isTimeUp()) {
+ Log.e(TAG, "Timeout");
+ }
+ }
+
+ /**
+ * Finds buttons with text or content description that match pattern {@link NEXT_BTN_PATTERN}
+ * and click on them.
+ *
+ * @return {@code true} if any button found, {@code false} otherwise
+ */
+ private boolean clickAvailableNextButton() {
+ return clickAnyButton(getUiDevice().findObjects(NAVIGATION_BTN_TEXT_SELECTOR))
+ || clickAnyButton(getUiDevice().findObjects(NAVIGATION_BTN_DESC_SELECTOR));
+ }
+
+ /**
+ * Clicks any button from given list.
+ *
+ * @param buttons list of buttons to click
+ * @return {@code true} if there is any button clicked successfully, {@code false} otherwise
+ */
+ private boolean clickAnyButton(List<UiObject2> navigationBtns) {
+ for (UiObject2 obj : navigationBtns) {
+ // Skip widget with package name in mPackageNameBlacklist.
+ String pkgName = WidgetUtils.getPackageName(obj);
+ if (mPackageNameBlacklist != null && mPackageNameBlacklist.contains(pkgName)) {
+ continue;
+ }
+
+ if (safeClick(obj)) {
+ // Returns immediately after the first 'Next' button is found and clicked; because
+ // after clicking the current view hierarchy will change; the found navigation
+ // buttons will be stale.
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Iterates OEM widgets and act on found ones if necessary.
+ *
+ * @param oemWidgets {@link List} of {@link OemWidget} to operate
+ */
+ private void iterateOemWidgets(List<OemWidget> oemWidgets) {
+
+ for (OemWidget widget : oemWidgets) {
+ BySelector selector = BySelectorHelper.getSelector(widget);
+
+ if (getUiDevice().hasObject(selector)) {
+ Log.d(TAG, "Found OEM widget: " + widget.toString());
+
+ if (widget.getAction().equals(ACTION_CHECK)) {
+ safeClick(getUiDevice().findObject(selector));
+ } else if (widget.getAction().equals(ACTION_SCROLL)){
+ safeFling(
+ getUiDevice().findObject(selector),
+ Direction.valueOf(widget.getScrollDirection()));
+ } else if (widget.getAction().equals(ACTION_CLICK)) {
+ safeClick(getUiDevice().findObject(selector));
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets list of package names which should not be skipped.
+ *
+ * @param blacklist list of package names
+ */
+ public void setPackageNameBlacklist(Set<String> blacklist) {
+ mPackageNameBlacklist = blacklist;
+ }
+}