Android Open Source - Cafe View Helper






From Project

Back to project page Cafe.

License

The source code is released under:

Apache License

If you think the Android project Cafe listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2011 Baidu.com Inc//from  w w w.  ja v a  2 s  .c o  m
 *
 * 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.baidu.cafe.local.traveler;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import android.text.InputType;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.ViewFlipper;

/**
 * define view's action
 * 
 * @author luxiaoyu01@baidu.com
 * @date 2011-11-28
 * @version
 * @todo
 */
public class ViewHelper {
    public final static String             ACTION_CLICK              = "click";
    public final static String             ACTION_TEXT               = "text";
    public final static String             ACTION_LONG_CLICK         = "longclick";
    public final static String             ACTION_SLIDE              = "slide";
    public final static String             ACTION_LISTVIEW           = "listview";

    public static ArrayList<String>        mBlackList                = new ArrayList<String>();

    private static int                     mGloablStep               = 0;
    private static boolean                 mIsLogged                 = false;
    private static ArrayList<View>         mList                     = new ArrayList<View>();
    private static ArrayList<AbstractList> mAbstractLists            = new ArrayList<AbstractList>();

    private final static int               SLEEP_TIME                = 3000;
    private final static int               INTERNET_SLEEP_TIME       = 5000;
    private final static int               TIMEOUT_WAIT_FOR_LOADING  = 1000 * 5;
    private final static int               INTERVAL_WAIT_FOR_LOADING = 500;
    private final static int               TYPE_PASSWORD             = InputType.TYPE_CLASS_TEXT
                                                                             | InputType.TYPE_TEXT_VARIATION_PASSWORD;
    private final static int               TYPE_VISIBLE_PASSWORD     = InputType.TYPE_CLASS_TEXT
                                                                             | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;

    private final static int               RET_PASS                  = 0;
    private final static int               RET_IN_WHITE_LIST         = 1;
    private final static int               RET_IN_BLACK_LIST         = 2;
    private final static int               RET_NOT_SUITABLE          = 3;
    private final static int               RET_NO_ACTION             = 4;
    private final static int               RET_NO_LISTENER           = 5;
    private final static int               RET_NOT_IN_SCREEN         = 6;
    private final static int               RET_IN_LIST               = 7;

    public static class AbstractList {
        public View list;
        public int  indexAtActivity = 0;
        public int  cursor          = 0;

        public AbstractList(View list, int indexAtActivity, int cursor) {
            this.list = list;
            this.indexAtActivity = indexAtActivity;
            this.cursor = cursor;
        }
    }

    public static void sleep() {
        APPTraveler.local.sleep(getSleepTime());
    }

    private static int getSleepTime() {
        //        if (mUseInternet && mGloablStep++ <= 5) {
        //            Logger.println("INTERNET_SLEEP_TIME: " + INTERNET_SLEEP_TIME);
        //            return INTERNET_SLEEP_TIME;
        //        }
        return SLEEP_TIME;
    }

    public static <T extends View> ArrayList<T> getAllOperatableViews(Class<T> classToFilterBy) {
        ArrayList<View> operatableViews = getAllOperatableViews();
        ArrayList<T> views = new ArrayList<T>();

        for (View view : operatableViews) {
            if (classToFilterBy.isAssignableFrom(view.getClass())) {
                views.add(classToFilterBy.cast(view));
            }
        }
        operatableViews = null;
        return views;
    }

    public static ArrayList<View> sortByDistanceYFromCenter(ArrayList<View> views) {
        final int centerY = APPTraveler.mDisplayY / 2;
        Comparator<View> comparator = new Comparator<View>() {

            @Override
            public int compare(View lhs, View rhs) {
                int distanceLeft = Math.abs(APPTraveler.local.getViewCenter(lhs)[1] - centerY);
                int distanceRight = Math.abs(APPTraveler.local.getViewCenter(rhs)[1] - centerY);
                return distanceLeft - distanceRight;
            }

        };
        Collections.sort(views, comparator);
        return views;
    }

    public static ArrayList<View> getAllOperatableViews() {
        ArrayList<View> views = APPTraveler.local.getCurrentViews();
        //        ArrayList<View> views = CafeCaller.getLocal().getViews();//not onlySufficientlyVisible
        ArrayList<View> operatableViews = new ArrayList<View>();
        if (views.size() == 0) {
            Logger.println("views.size() == 0");
        }

        for (View view : views) {
            if (!view.isShown() || APPTraveler.local.isSize0(view)) {
                continue;
            }

            if (view instanceof ViewGroup) {
                operatableViews.addAll(getListItems(view));
            } else {
                if (isAvailable(view, true)) {
                    operatableViews.add(view);
                }
            }
        }
        if (operatableViews.size() == 0) {
            Logger.println("operatableViews.size() ==0");
        }

        return sortByDistanceYFromCenter(operatableViews);
    }

    public static boolean handlePasswordEditText() {
        if (mIsLogged) {
            return false;
        }

        // fill user name & password
        EditText password = getPasswordEditText();
        EditText userName = null;
        if (null == password) {
            return false;
        } else {
            userName = getUserNameEditText(password);
        }
        if (null == userName) {
            return false;
        }

        Logger.println(String.format("FIND username [%s] & password [%s]", userName, password));
        Logger.println("username:" + APPTraveler.mUsername);
        Logger.println("password:" + APPTraveler.mPassword);
        enterText(userName, APPTraveler.mUsername);
        enterText(password, APPTraveler.mPassword);
        if (clickLoginButton(password)) {
            return mIsLogged = true;
        }

        return false;
    }

    private static boolean clickLoginButton(EditText password) {
        //        ArrayList<View> viewsBelow = getViewsBelow(password);
        View loginButton = getLoginButton(APPTraveler.local.getCurrentViews());
        if (null == loginButton) {
            Logger.println("null == loginButton");
            return false;
            //            int[] xy = new int[2];
            //            password.getLocationOnScreen(xy);
            //            loginButton = getNearestView(xy[0], xy[1], viewsBelow);
        }

        int[] xy = new int[2];
        loginButton.getLocationOnScreen(xy);
        APPTraveler.screenShot(xy);
        APPTraveler.local.clickViewWithoutAssert(loginButton);
        return true;
    }

    private static View getLoginButton(ArrayList<View> buttons) {
        String loginString1 = APPTraveler.local.getTestRString("login1");
        String loginString2 = APPTraveler.local.getTestRString("login2");

        for (View button : buttons) {
            if (button instanceof Button) {
                String text = ((Button) button).getText().toString();
                if (text.contains(loginString1) && text.contains(loginString2)) {
                    Logger.println("loginButton: " + text);
                    return button;
                }
            }
        }
        return null;
    }

    private static ArrayList<View> getViewsBelow(View anchor) {
        int[] xyAnchor = new int[2];
        anchor.getLocationOnScreen(xyAnchor);
        ArrayList<View> viewsBelow = new ArrayList<View>();
        for (View view : APPTraveler.local.getCurrentViews()) {
            int[] xy = new int[2];
            view.getLocationOnScreen(xy);
            if (xy[1] > xyAnchor[1]) {
                viewsBelow.add(view);
            }
        }
        return viewsBelow;
    }

    private static EditText getPasswordEditText() {
        ArrayList<EditText> editTexts = APPTraveler.local.getCurrentViews(EditText.class);
        for (EditText editText : editTexts) {
            int type = editText.getInputType();
            Logger.println("" + editText + "InputType:" + type);
            if (type == TYPE_PASSWORD || type == TYPE_VISIBLE_PASSWORD) {
                return editText;
            }
        }
        return null;
    }

    private static EditText getUserNameEditText(EditText password) {
        int[] passwordXY = new int[2];
        password.getLocationOnScreen(passwordXY);

        // get edittexts above password edittext
        ArrayList<EditText> editTexts = APPTraveler.local.getCurrentViews(EditText.class);
        ArrayList<View> upEditTexts = new ArrayList<View>();
        for (EditText editText : editTexts) {
            int[] xy = new int[2];
            editText.getLocationOnScreen(xy);
            if (xy[1] < passwordXY[1]) {
                upEditTexts.add(editText);
            }
        }

        return (EditText) getNearestView(passwordXY[0], passwordXY[1], upEditTexts);
    }

    private static View getNearestView(int x, int y, ArrayList<View> candidate) {
        double minDistance = Double.MAX_VALUE;
        View nearestView = null;
        for (View view : candidate) {
            int[] xy = new int[2];
            view.getLocationOnScreen(xy);
            double distance = Util.getDistance(x, y, xy[0], xy[1]);
            if (distance < minDistance) {
                minDistance = distance;
                nearestView = view;
            }
        }
        return nearestView;
    }

    private static ArrayList<View> getListItems(View view) {
        ArrayList<View> items = new ArrayList<View>();

        //        if (mList.contains(view)) {
        //            Logger.println(view + " is old");
        //            return items;
        //        }

        if (view instanceof ListView) {
            items.add(view);

        } else if (view instanceof ScrollView) {
            items = getVisibleViews(getScrollViewListItems((ViewGroup) view));
        } else if (view instanceof GridView) {
            // TODO
        }

        //        if (items.size() != 0) {
        //            Logger.println("add " + view + " to list");
        //            mList.add(view);
        //        }
        return items;
    }

    private static ArrayList<View> getListViewListItems(ListView listView) {
        ArrayList<View> items = new ArrayList<View>();
        Logger.println("getListViewListItems: " + listView);
        for (int i = listView.getFirstVisiblePosition(); i <= listView.getLastVisiblePosition(); i++) {
            Logger.println("listitem: " + listView.getChildAt(i).toString());
            items.add(listView.getChildAt(i));
        }
        return items;
    }

    private static boolean isSuitableTextView(TextView textView) {
        if (isInList(textView)) {
            return false;
        }
        return true;
    }

    private static boolean isInList(View view) {
        View parent = view;
        while ((parent = getParent(parent)) != null) {
            if (isList(parent)) {
                return true;
            }
        }
        return false;
    }

    public static String getViewText(View view) {
        return view instanceof TextView ? ((TextView) view).getText().toString() : "";
    }

    private static boolean hasListener(View view) {
        if (APPTraveler.local.getListener(view, View.class, "mOnClickListener") != null) {
            return true;
        }
        if (APPTraveler.local.getListener(view, View.class, "mOnLongClickListener") != null) {
            return true;
        }
        if (APPTraveler.local.getListener(view, View.class, "mOnTouchListener") != null) {
            return true;
        }
        if (APPTraveler.local.getListener(view, View.class, "mOnKeyListener") != null) {
            return true;
        }
        return false;
    }

    private static ArrayList<View> getVisibleViews(ArrayList<View> views) {
        ArrayList<View> visibleViews = new ArrayList<View>();
        for (View view : views) {
            if (APPTraveler.local.isInScreen(view)) {
                visibleViews.add(view);
            }
        }
        return visibleViews;
    }

    private static ArrayList<View> getScrollViewListItems(ViewGroup viewGroup) {
        ArrayList<View> children = new ArrayList<View>();
        if (hasListItems(viewGroup)) {
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                children.add(viewGroup.getChildAt(i));
            }
            return children;
        }

        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            View child = viewGroup.getChildAt(i);
            if (child instanceof ViewGroup) {
                ArrayList<View> grandson = getScrollViewListItems((ViewGroup) child);
                if (grandson.size() != 0) {
                    Logger.println("father: " + getViewText(child));
                    return grandson;
                }
            }
        }

        return children;
    }

    private static boolean hasListItems(ViewGroup viewGroup) {
        if (viewGroup.getChildCount() < 3) {
            return false;
        }

        int width = viewGroup.getChildAt(0).getWidth();
        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            View child = viewGroup.getChildAt(i);

            // Children must be clickable.
            if (!child.isClickable()) {
                return false;
            }

            // Width of children must be same.
            if (child.getWidth() != width) {
                return false;
            }
        }

        return true;
    }

    private static int getListIndex(View targetList) {
        ArrayList<? extends View> lists = APPTraveler.local.getCurrentViews(targetList.getClass());
        for (int i = 0; i < lists.size(); i++) {
            if (lists.get(i).equals(targetList)) {
                return i;
            }
        }
        Logger.println("Can not find " + targetList.toString() + "!!!");
        return -1;
    }

    private static void addAbstractList(View list, int indexAtActivity) {
        if (getAbstractList(list) == null) {
            mAbstractLists.add(new AbstractList(list, indexAtActivity, 1));
        }
    }

    public static AbstractList getAbstractList(View list) {
        for (AbstractList abstractList : mAbstractLists) {
            if (abstractList.list.equals(list)) {
                return abstractList;
            }
        }
        return null;
    }

    public static ArrayList<Operation> getViewOperations(View view, int viewIndex) {
        ArrayList<String> actions = getViewActions(view);
        ArrayList<Operation> operations = new ArrayList<Operation>();

        for (String action : actions) {
            Operation operation = new Operation(view, viewIndex, action,
                    APPTraveler.remote.getTopActivity());
            //            Logger.println("operation: " + operation);
            operations.add(operation);
        }

        return operations;
    }

    public static ArrayList<String> getViewActions(View view) {
        ArrayList<String> actions = new ArrayList<String>();

        if (view instanceof ListView) {
            ListView listView = (ListView) view;
            int lines = listView.getLastVisiblePosition() - listView.getFirstVisiblePosition();
            // Ignore the last line in case that the last line is not visible completely.
            for (int i = 1; i <= lines; i++) {
                //                Logger.println("add ACTION_LISTVIEW" + i);
                actions.add(ACTION_LISTVIEW + i);
            }
            addAbstractList(listView, getListIndex(listView));
            return actions;
        }
        //        else if (view instanceof ScrollView) {
        //            ScrollView scrollView = (ScrollView) view;
        //            int lines = getScrollViewVisibleChildCount(scrollView);
        //            for (int i = 1; i <= lines; i++) {
        //                actions.add(ACTION_SCROLLVIEW + i);
        //            }
        //            addAbstractList(scrollView, getListIndex(scrollView));
        //            return actions;
        //        } else if (view instanceof GridView) {
        //
        //        }

        if (view instanceof EditText) {
            actions.add(ACTION_TEXT);
            return actions;
        }

        if (isInList(view)) {
            return actions;
        }

        // TextView is not clickable but it's parent is clickable
        if (view.isClickable() || isClickableTextView(view)) {
            actions.add(ACTION_CLICK);
        }

        // TODO EditText longclick is not repeatable, so it is disable.
        //        if (view.isLongClickable() && !(view instanceof EditText)) {
        //            actions.add(ACTION_LONG_CLICK);
        //        }

        if (view instanceof ViewFlipper) {
            actions.add(ACTION_SLIDE);
        }

        // content menu

        // menu
        // TODO how to make sure that there is a menu ?

        return actions;
    }

    public static void waitForLoading() {
        long end = System.currentTimeMillis() + TIMEOUT_WAIT_FOR_LOADING;
        while (ViewHelper.hasLoadingView()) {
            try {
                Thread.sleep(INTERVAL_WAIT_FOR_LOADING);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (System.currentTimeMillis() > end) {
                Logger.println("waitForLoading timeout!");
                break;
            }
        }
    }

    /**
     * Find indeterminate ProgressBar from current visibile views.
     * 
     * @param views
     * @return
     */
    private static boolean hasLoadingView() {
        ArrayList<View> views = APPTraveler.local.getCurrentViews();
        for (View view : views) {
            if (view instanceof ProgressBar) {
                ProgressBar progressBar = (ProgressBar) view;
                if (progressBar.isIndeterminate()) {
                    return true;
                }
            }
        }
        return false;
    }

    private static boolean isClickableTextView(View view) {
        if (!(view instanceof TextView)) {
            return false;
        }
        return hasClickableParent(view);
    }

    private static boolean hasClickableParent(View view) {
        View parentView = view;
        while ((parentView = getParent(parentView)) != null) {
            if (parentView.isClickable()) {
                return true;
            }
        }
        return false;
    }

    private static View getParent(View view) {
        if (!(view.getParent() instanceof View)) {
            return null;
        }
        return (View) view.getParent();
    }

    private static boolean isList(View view) {
        return view instanceof ListView || view instanceof ScrollView || view instanceof GridView ? true
                : false;
    }

    private static boolean isInWhiteList(View view) {
        return false;
    }

    private static boolean isInBlackList(View view) {
        for (String str : mBlackList) {
            if (APPTraveler.local.getViewText(view).equals(str)) {
                return true;
            }
        }

        return false;
    }

    public static boolean isAvailable(View view, boolean careListener) {
        int ret = isTargetView(view, careListener);
        String retString = Util.getReturnValueName(ViewHelper.class, ret);
        if (ret <= RET_IN_WHITE_LIST) {
            //            Logger.println("Passed [" + retString + "] " + view.toString() + " " + getViewText(view));
            return true;
        } else {
            //            Logger.println("Failed [" + retString + "] " + view.toString() + " " + getViewText(view));
            return false;
        }
    }

    private static int isTargetView(View view, boolean careListener) {
        if (isInBlackList(view)) {
            return RET_IN_BLACK_LIST;
        }

        if (isInWhiteList(view)) {
            return RET_IN_WHITE_LIST;
        }

        if (!isSuitable(view)) {
            return RET_NOT_SUITABLE;
        }

        if (getViewActions(view).size() == 0) {
            return RET_NO_ACTION;
        }

        if (!APPTraveler.local.isInScreen(view)) {
            return RET_NOT_IN_SCREEN;
        }

        //        if (careListener && !hasListener(view)) {
        //            return RET_NO_LISTENER;
        //        }

        if (view instanceof TextView && !isSuitableTextView((TextView) view)) {
            return RET_IN_LIST;
        }
        return RET_PASS;
    }

    private static boolean isSuitable(View view) {
        if (!view.isShown()) {
            return false;
        }

        //        if (view instanceof ViewGroup) {
        //            return false;
        //        }

        if (!view.isEnabled()) {
            return false;
        }

        return true;
    }

    public static void goBack(String reason) {
        Logger.println("goBack because of [" + reason + "]");
        APPTraveler.local.hideInputMethod();
        APPTraveler.remote.sleep(SLEEP_TIME);

        APPTraveler.remote.goBack();
        APPTraveler.remote.sleep(SLEEP_TIME);
    }

    public static void enterText(EditText editText, String text) {
        // if text == null will cause app crash!
        if (null == text || text.length() == 0) {
            Logger.println("null == text || text.length() == 0");
        } else {
            APPTraveler.local.enterText(editText, text);
            APPTraveler.local.sleep(500);
        }
    }
}




Java Source Code List

com.baidu.cafe.CafeExceptionHandler.java
com.baidu.cafe.CafeListener.java
com.baidu.cafe.CafeServiceTestCase.java
com.baidu.cafe.CafeTestCase.java
com.baidu.cafe.CafeTestRunner.java
com.baidu.cafe.TearDownHelper.java
com.baidu.cafe.local.DESEncryption.java
com.baidu.cafe.local.FPSTracer.java
com.baidu.cafe.local.FileUtils.java
com.baidu.cafe.local.LocalLib.java
com.baidu.cafe.local.Log.java
com.baidu.cafe.local.NetworkUtils.java
com.baidu.cafe.local.SnapshotHelper.java
com.baidu.cafe.local.record.CafeWebViewClient.java
com.baidu.cafe.local.record.OutputEvent.java
com.baidu.cafe.local.record.ViewRecorderSDK.java
com.baidu.cafe.local.record.ViewRecorder.java
com.baidu.cafe.local.record.WebElementRecorder.java
com.baidu.cafe.local.traveler.APPTraveler.java
com.baidu.cafe.local.traveler.Logger.java
com.baidu.cafe.local.traveler.Operation.java
com.baidu.cafe.local.traveler.Util.java
com.baidu.cafe.local.traveler.ViewHelper.java
com.baidu.cafe.remote.ArmsBinder.java
com.baidu.cafe.remote.ArmsBootupReceiver.java
com.baidu.cafe.remote.Arms.java
com.baidu.cafe.remote.Armser.java
com.baidu.cafe.remote.BatteryState.java
com.baidu.cafe.remote.LockActivity.java
com.baidu.cafe.remote.Log.java
com.baidu.cafe.remote.MonkeyNetwork.java
com.baidu.cafe.remote.MyIntent.java
com.baidu.cafe.remote.SystemLib.java
com.baidu.cafe.remote.UILib.java
com.baidu.cafe.remote.ViewPropertyProvider.java
com.baidu.cafe.utils.CommandResult.java
com.baidu.cafe.utils.ReflectHelper.java
com.baidu.cafe.utils.ShellExecute.java
com.baidu.cafe.utils.Strings.java
com.baidu.cafe.utils.TreeNode.java