python+uiautomator2二次封装

#!python3.7
# -*- coding: utf-8 -*-

__author__ = 'haiertamendie'
__data__ = "2019-11-15 19-56"

import base64

"""
界面元素基础操作
"""
import uiautomator2 as u2
from Config.Config import Config
from Api.Public.PyApiLog import PyApiLog
import datetime
import os
import time
from unittest import TestCase


class Action:
    def __init__(self):
        pass

    def connect_wifi(self, ip):
        """
        通过WiFi连接设备:ip根据情况自己修改
        :param ip:
        :return:
        """
        return u2.connect_wifi(ip)

    def connect_usb(self):
        """
        通过USB连接设备
        :return:
        """
        return u2.connect_usb()

    def healthcheck(self):
        """
        检查并维持设备端守护进程处于运行状态
        :return:
        """
        self.device.healthcheck()

    def app_start(self, package_name,
                  activity=None,
                  extras={},
                  wait=True,
                  stop=True,
                  unlock=False,
                  launch_timeout=30,
                  use_monkey=False):
        """
        启动APP
        :param package_name:
        :param activity:
        :param extras:
        :param wait:
        :param stop:
        :param unlock:
        :param launch_timeout:
        :param use_monkey:
        :return:
        """
        self.device.app_start(package_name, activity=activity, extras=extras, wait=wait, stop=stop, unlock=unlock,
                              launch_timeout=launch_timeout, use_monkey=use_monkey)

    def app_stop(self, package_name):
        """
        关闭app
        :param package_name: 应用包名
        :return:
        """
        self.device.app_stop(package_name)

    def app_clear(self, package_name):
        """
        清除app缓存
        :param package_name: 应用包名
        :return:
        """
        self.device.app_clear(package_name)

    def get_app_info(self, package_name):
        """
        获取应用信息
        :param package_name: 应用包名
        :return:
        """
        return self.device.app_info(package_name)

    def app_stop_all(self, excludes=[]):
        """
        关闭excludes中的所有应用
        :param excludes: 应用包名集合
        :return:
        """
        self.device.app_stop_all(excludes)

    def get_app_list_running(self):
        """
        获取已启动的应用
        :return:
        """
        return self.device.app_list_running()

    def wait_activity(self, activity, timeout=10):
        """
        等待activity加载出来
        :param activity:
        :param timeout:
        :return:
        """
        self.wait_activity(activity=activity, timeout=timeout)

    def app_wait(self, package_name, timeout=20.0,
                 front=False):
        """
        等待应用启动
        :param package_name: 应用包名
        :param timeout:  超时时间
        :param front:
        :return:
        """
        return self.device.app_wait(package_name, timeout=timeout, front=front)

    def app_insatll(self, url, installing_callback=None, server=None):
        """
        安装应用
        :param url: 设备名字或者地址
        :param installing_callback:
        :param server:
        :return:
        """
        self.device.app_install(url, installing_callback=installing_callback, server=server)

    def app_uninstall(self, package_name):
        """
        卸载应用
        :param package_name: 应用包名
        :return:
        """
        self.device.app_uninstall(package_name)

    def app_uninstall_all(self, excludes=[], verbose=False):
        """
        卸载多个应用
        :param excludes: 应用包名集合
        :param verbose:
        :return:
        """
        self.device.app_uninstall_all(excludes=excludes, verbose=verbose)

    def get_element_xpath(self, xpath):
        """
        根绝xpath路径获取元素
        :param xpath: xpath路径
        :return:
        """
        return self.device.xpath(xpath)

    def get_elements(self, childCount=None, **kwargs):
        """获取元素
        @:param childCount 子元素数量
        """
        ele = self.device(**kwargs)
        if childCount:
            eles = []
            for i in ele:
                if i.info.get("childCount") == childCount:
                    eles.append(i)
            return eles
        else:
            return ele

    def get_count(self, **kwargs):
        """
        获取元素个数
        :param kwargs: 元素定位
        :return:
        """
        return self.device(**kwargs).count

    def get_child_element(self, element, childCount=None, **kwargs):
        """
        获取子对象
        :param element: 元素对象
        :param childCount:
        :param kwargs:
        :return:
        """
        ele = element.child(**kwargs)
        if childCount == None or len(ele) == 1:
            return ele
        else:
            eles = []
            for i in ele:
                if i.info.get("childCount") == childCount:
                    eles.append(i)
            return eles

    def get_left_element(self, element, **kwargs):
        """
        获取element左侧元素
        :param element: 元素对象
        :param kwargs:
        :return:
        """
        return element.left(**kwargs)

    def get_right_element(self, element, **kwargs):
        """获取element右侧元素"""
        return element.right(**kwargs)

    def get_up_element(self, element, **kwargs):
        """
        获取element上方元素
        :param element: 元素对象
        :param kwargs:
        :return:
        """
        return element.up(**kwargs)

    def get_down_element(self, element, **kwargs):
        """
        获取element下方元素"
        :param element: 元素对象
        :param kwargs: 
        :return: 
        """""
        return element.down(**kwargs)

    def get_sibling_elements(self, index=0, **kwargs):
        """
        获取兄弟元素
        :param index: 第几个兄弟,默认为全部
        :param kwargs: 元素定位(唯一)
        :return:
        """
        self.wait(**kwargs)
        if index == 0:
            return self.device(**kwargs).sibling()
        return self.device(**kwargs).sibling()[index]

    def get_sibling_elements_by_element(self, element, **kwargs):
        """
        获取兄弟元素
        :param element: 元素
        :param kwargs: 兄弟元素定位(唯一)
        :return:
        """
        return element.sibling(**kwargs)

    def click(self, **kwargs):
        """
        点击元素
        :param index: 索引值
        :param kwargs: 元素定位()
        :return:
        """
        self.device(**kwargs).click()

    def click_xpath(self, xpath, timeout=5):
        """
        根据xpath路径点击元素
        :param xpath:
        :param timeout:
        :return:
        """
        self.device.xpath(xpath).click(timeout=timeout)

    def click_element(self, element):
        """
        点击元素
        :param element: 元素对象
        :return:
        """
        element.click()

    def click_child_element(self, element, **kwargs):
        """
        点击element的子元素
        :param element: 元素对象
        :param kwargs: 子元素定位信息
        :return:
        """
        ele = self.get_child_element(element, **kwargs)[0]
        self.click_element(ele)

    def click_by_point(self, x, y):
        """
        点击坐标点
        :param x: 横坐标
        :param y: 纵坐标
        :return:
        """
        self.device.click(x, y)

    def double_click(self, x, y, duration=0.1):
        """双击
        @:param duration 间隔
        """
        self.device.double_click(x, y, duration=duration)

    def long_click(self, duration=10, timeout=10, **kwargs):
        """
        长按指定的对象
        :param duration: 持续时间
        :param timeout: 超时时间
        :param kwargs: 元素定位
        :return:
        """
        self.device(**kwargs).long_click(duration=duration, timeout=timeout)

    def long_click_by_element(self, element, duration=10, timeout=10):
        """
        长按
        :param element: 元素对象
        :param duration: 持续时间
        :param timeout: 超时时间
        :return:
        """
        element.long_click(duration=duration, timeout=timeout)

    def long_click_by_point(self, x, y):
        """
        长按坐标点
        :param x: 横坐标
        :param y: 纵坐标
        :return:
        """
        self.device.long_click(x, y)

    def get_element_info(self, **kwargs):
        """
        获取元素信息
        :param kwargs: 元素定位
        :return:
        """
        return self.device(**kwargs).info

    def get_info_by_element(self, element):
        """
        获取元素信息
        :param element: 元素对象
        :return:
        """
        return element.info

    def input_text(self, content, **kwargs):
        """
        输入文本
        :param content: 文本内容
        :param kwargs: 元素定位信息
        :return:
        """
        self.wait(**kwargs)
        self.device(**kwargs).set_text(content)
        self.press("enter")

    def input_text_xpath(self, content, xpath):
        """
        输入文本
        :param content: 文本内容
        :param xpath: 元素xpath定位信息
        :return:
        """
        self.wait_xpath(xpath)
        element = self.get_element_xpath(xpath)
        self.click_element(element)
        element.set_text(content)

    def input_text_by_element(self, element, content):
        """输入"""
        self.click_element(element)
        element.set_text(content)
        self.press("enter")

    def clear_text(self, **kwargs):
        """
        清除输入框数据
        :param kwargs: 输入文本框定位
        :return:
        """
        self.device(**kwargs).clear_text()

    def clear_text_by_element(self, element):
        """清除数据"""
        element.clear_text()

    def click0(self, **kwargs):
        """点击UI对象中心位置"""
        self.device(**kwargs).click0()

    def click0_by_element(self, element):
        """点击UI对象中心位置"""
        element.click0()

    def click_bottomright(self, **kwargs):
        """点击UI对象右下角"""
        self.device(**kwargs).click.bottomright()

    def click_bottomright_by_element(self, element):
        """点击UI对象右下角"""
        element.click.bottomright()

    def click_topleft(self, **kwargs):
        """点击UI对象左上角"""
        self.device(**kwargs).click.topleft()

    def click_topleft_by_element(self, element):
        """点击UI对象左上角"""
        element.click.topleft()

    def long_click_bottomright(self, **kwargs):
        """长按UI对象右下角"""
        self.device(**kwargs).long_click.bottomright()

    def long_click_bottomright_by_element(self, element):
        """长按UI对象右下角"""
        element.long_click.bottomright()

    def long_click_topleft(self, **kwargs):
        """长按UI对象左上角"""
        self.device(**kwargs).long_click.topleft()

    def long_click_topleft_by_element(self, element):
        """长按UI对象左上角"""
        element.long_click.topleft()

    def drag_to_point(self, element, x, y, duration=1):
        """拖动指定对象到x,y位置,0.5s完成"""
        element.drag.to(x, y, duration=duration)

    def drag_to_element(self, element, **kwargs):
        """拖拽某一UI对象到另外一个UI对象(中心)"""
        element.drag.to(**kwargs, steps=100)

    def refresh(self):
        """刷新页面"""
        wedith = self.get_window_size()[0]
        height = self.get_window_size()[1]
        self.swipe(wedith / 2, height * 1 / 4, wedith / 2, height * 5 / 6)

    def swipe_right(self, **kwargs):
        """从UI对象的中心滑动到UI对象的右边缘"""
        self.device(**kwargs).swipe.right()

    def swipe_right_by_element(self, element):
        """从UI对象的中心滑动到UI对象的右边缘"""
        element.swipe.right()

    def swipe_up(self, **kwargs):
        """从UI对象的中心滑动到UI对象的上边缘"""
        self.device(**kwargs).swipe.up()

    def swipe_up_screen(self, scre=1, steps=100):
        """
        向上滑动屏幕,默认为一屏
        :param scre: 滑动比例
        :return:
        """
        device_info = self.get_device_info()
        height = device_info.get("displayHeight")
        width = device_info.get("displayWidth")
        self.device.swipe(width / 2, height * 8 * scre / 9, width / 2, height / 9, steps=steps)

    def swipe_down_screen(self, scre=1, steps=100):
        """
        向下滑动屏幕,默认为一屏
        :param scre: 滑动比例
        :return:
        """
        device_info = self.get_device_info()
        height = device_info.get("displayHeight")
        width = device_info.get("displayWidth")
        self.device.swipe(width / 2, height / 9, width / 2, height * 8 * scre / 9, steps=steps)

    def swipe_up_by_element(self, element):
        """从UI对象的中心滑动到UI对象的上边缘"""
        element.swipe.up()

    def swipe_left(self, **kwargs):
        """从UI对象的中心滑动到UI对象的左边缘"""
        self.device(**kwargs).swipe.left()

    def swipe_left_by_element(self, element):
        """从UI对象的中心滑动到UI对象的左边缘"""
        element.swipe.left()

    def swipe_down(self, **kwargs):
        """从UI对象的中心滑动到UI对象的下边缘"""
        self.device(**kwargs).swipe.down()

    def swipe_down_by_element(self, element):
        """从UI对象的中心滑动到UI对象的下边缘"""
        element.swipe.down()

    def pinch_In(self, **kwargs):
        """从边缘到中心"""
        self.device(**kwargs).pinch.In(percent=100, steps=10)

    def pinch_In_by_element(self, element):
        """从边缘到中心"""
        element.pinch.In(percent=100, steps=10)

    def pinch_Out(self, percent=33, steps=100):
        """从屏幕外侧向中心滑动,percent为左右起始位置占两边的比例"""
        self.device().pinch_out(percent=percent, steps=steps)

    def pinch_Out_element(self, element, percent=33, steps=100):
        """从中心到边缘"""
        element.pinch_out(percent=percent, steps=steps)

    def set_implicitly_wait(self, timeout=30):
        """设置全局最长等待时间"""
        return self.device.implicitly_wait(timeout)

    def click_wait(self, timeout=10, **kwargs):
        """
        当timeout s内对象出现就点击
        :param timeout: 超时时间
        :param kwargs: 元素定位
        :return:
        """
        self.device(**kwargs).click_exists(timeout)

    def click_wait_xpath(self, xpath, timeout=10):
        """
        当timeout s内对象出现就点击
        :param xpath: xpath定位
        :param timeout: 超时时间
        :return:
        """
        self.wait_xpath(xpath, timeout=timeout)
        self.click_xpath(xpath)

    def click_gone(self, maxretry=10, interval=1.0, **kwargs):
        """
        点击并轮询对象直到消失
        :param maxretry: 最多点击次数
        :param interval: 轮询时间间隔
        :param kwargs: 元素定位
        :return:
        """
        self.device(**kwargs).click_gone(maxretry=maxretry, interval=interval)

    def wait_exists_by_element(self, element, timeout=10):
        """
        等待UI对象出现
        :param element: 元素对象
        :param timeout: 超时时间
        :return:
        """
        return element.exists(timeout=timeout)

    def wait(self, timeout=10, **kwargs):
        """
        等待
        :param timeout: 超时时间
        :param kwargs: 元素定位
        :return:
        """
        return self.device(**kwargs).wait(timeout)

    def wait_should_be_contains(self, timeout=10, **kwargs):
        """
        等待包含元素,超时抛出错误
        :param timeout: 超时时间
        :param kwargs: 元素定位
        :return:
        """
        self.device(**kwargs).must_wait(exists=True, timeout=timeout)

    def wait_xpath(self, xpath, timeout=10):
        """
        等待
        :param xpath: xpath路径
        :param timeout: 超时时间
        :return:
        """
        return self.device.xpath(xpath).wait(timeout=timeout)

    def wait_gone(self, timeout=10, **kwargs):
        """
        等待UI对象消失
        :param timeout: 超时时间
        :param kwargs: 元素定位
        :return:
        """
        return self.device(**kwargs).wait_gone(timeout=timeout)

    def wait_gone_xpath(self, xpath, timeout=10):
        """
        等待UI对象消失
        :param xpath: xpath定位
        :param timeout: 超时时间
        :return:
        """
        return self.device.xpath(xpath).wait_gone(timeout=timeout)

    def wait_gone_by_element(self, element, timeout=3000):
        """
        等待UI对象消失
        :param element: 元素对象
        :param timeout: 超时时间
        :return:
        """
        return element.wait_gone(timeout=timeout)

    def scroll_up(self, steps=10):
        """
        向上滑动
        :param steps: 步长
        :return:
        """
        self.device(scrollable=True).scroll(steps=steps)

    def scroll_up_to_content_element(self, max_scroll_num=15, **kwargs):
        """
        向上滑动直到某个元素出现
        :param max_scroll_num: 最大滑动次数
        :param kwargs: 元素定位
        :return:
        """
        self.sleep()
        num = 0
        while num < max_scroll_num:
            if self.exists(timeout=0.5, **kwargs):
                return True
            else:
                try:
                    self.swipe_up_screen(0.5, steps=20)
                except:
                    return False
            num = num + 1
            self.sleep(0.2)
        if num == max_scroll_num:
            return False
        else:
            return True

    def vert_backward(self):
        """
        向下滑动
        :return:
        """
        self.device(scrollable=True).scroll.vert.backward()

    def vert_backward_to_content_element(self, **kwargs):
        """
        向下滑动直到某个元素出现
        :param kwargs: 元素定位
        :return:
        """
        while True:
            if self.exists(**kwargs):
                break
            else:
                self.device(scrollable=True).scroll.vert.backward(steps=100)

    def scroll_to_beginning(self, steps=10, max_swipes=1000):
        """
        向左滑动到开始位置
        :param steps: 步长
        :param max_swipes:
        :return:
        """
        self.device(scrollable=True).scroll.horiz.toBeginning(steps=steps, max_swipes=max_swipes)

    def horiz_forward(self, steps=10):
        """
        向右滑动"
        :param steps: 步长
        :return: 
        """""
        self.device(scrollable=True).scroll.horiz.forward(steps=steps)

    def scroll_to_end(self, steps=10):
        """
        向结束方向滑动
        :param steps: 步长
        :return:
        """
        self.device(scrollable=True).scroll.toEnd(steps=steps)

    def scroll_to(self, **kwargs):
        """
        向前滚动到指定UI位置
        :param kwargs: 元素定位
        :return:
        """
        self.device(scrollable=True).scroll.to(**kwargs)

    def get_device_info(self):
        """
        获取设备信息
        :return:
        """
        return self.device.info

    def get_window_size(self):
        """
        获取窗口大小
        :return:
        """
        return self.device.window_size()

    def get_device_height(self):
        """
        获取设备的高度
        :return:
        """
        return self.device.info.get("displayHeight")

    def get_device_width(self):
        """
        获取设备的宽度
        :return:
        """
        return self.device.info.get("displayWidth")

    def screen_on(self):
        """
        打开屏幕
        :return:
        """
        self.device.screen.on()

    def screen_off(self):
        """
        关闭屏幕
        :return:
        """
        self.device.screen.off()

    def wakeup(self):
        """
        唤醒设备
        :return:
        """
        self.device.wakeup()

    def device_sleep(self):
        """
        关闭设备
        :return:
        """
        self.device.sleep()

    def sleep(self, seconds=2):
        """
        强制等待时间
        :param seconds:
        :return:
        """
        time.sleep(seconds)

    def press_home(self):
        """
        按home键
        :return:
        """
        self.device.press("home")

    def press_back(self):
        """
        按返回键
        :return:
        """
        self.device.press("back")

    def press(self, key):
        """
        按下键码
        :param key: 键码值
        :return:
        """
        self.device.press(key)

    def press_enter(self):
        """
        按下回车键
        :return:
        """
        self.device.press.enter()

    def swipe(self, sx, sy, ex, ey, steps=10):
        """
        从sx,sy坐标滑动至ex,ey坐标
        :param sx: 起点横坐标
        :param sy: 起点纵坐标
        :param ex: 终点横坐标
        :param ey: 终点纵坐标
        :param steps:
        :return:
        """
        self.device.swipe(sx, sy, ex, ey, steps=steps)

    def gesture(self, a, b, c, d, a1, b1, c1, d1, steps=100):
        """
        双指从(a,b),(c,d)滑动(a1,b1),(c1,d1),步长100
        :param a:
        :param b:
        :param c:
        :param d:
        :param a1:
        :param b1:
        :param c1:
        :param d1:
        :param steps:
        :return:
        """
        self.device.gesture((a, b), (c, d), (a1, b1), (c1, d1), steps=steps)

    def drag(self, sx, sy, ex, ey, steps=10):
        """
        从sx,sy坐标拖动至ex,ey坐标
        :param sx: 起点横坐标
        :param sy: 起点纵坐标
        :param ex: 终点横坐标
        :param ey: 终点纵坐标
        :param steps: 步长
        :return:
        """
        self.device.drag(sx, sy, ex, ey, steps=steps)

    def screenshot(self, name=""):
        """
        截屏
        :param name: 图片名字
        :return:
        """
        if name != "":
            path = os.path.join(self.path_screenshot, name + ".png")
        else:
            path = os.path.join(self.path_screenshot, datetime.datetime.now().strftime('%Y-%m-%d_%H_%M') + ".png")
        self.device.screenshot(path)

    def get_screenshot_as_base64(self):
        """
        截屏并转换成base64
        :return:
        """
        content = self.device.screenshot(format="raw")
        base64_data = base64.b64encode(content)
        # base64.b64decode(base64data)
        return str(base64_data, "utf-8")

    def dump(self, path):
        """
        将当前屏幕结构保存在本机,xml文件
        :param path: 保存路径
        :return:
        """
        self.device.dump_hierarchy(path)

    def notification(self):
        """
        打开通知消息
        :return:
        """
        self.device.notification()

    def open_quick_settings(self):
        """
        打开快捷设置栏
        :return:
        """
        self.device.open.quick_settings()

    def register_watcher_click(self, name, **kwargs):
        """
        创建并运行监听器
        :param name:
        :param kwargs:
        :return:
        """
        watcher = self.device.watcher(name).when(**kwargs).click(**kwargs)
        self.watchers_run()
        return watcher

    def remove_watcher(self, name):
        """
        移除监听器
        :param name: 监听器名字
        :return:
        """
        self.device.watcher(name).remove()

    def watchers(self):
        """
        获取所有监听器
        :return:
        """
        return self.device.watcher()

    def watchers_triggered(self, name):
        """
        获取所有已触发监听器
        :param name:
        :return:
        """
        return self.device.watcher(name).triggered

    def watchers_reset(self):
        """
        重置所有已触发的监视器
        :return:
        """
        self.device.watchers.reset()

    def watchers_run(self):
        """
        运行所有已注册的监听器
        :return:
        """
        self.device.watchers.run()

    def exists(self, timeout=10, **kwargs):
        """
        判断元素是否存在
        :param timeout: 超时时间
        :param kwargs: 元素定位
        :return:
        """
        return self.device(**kwargs).exists(timeout=timeout)

    def exists_xpath(self, xpath):
        """
        判断元素是否存在
        :param xpath: xpath路径
        :return:
        """
        return self.device.xpath(xpath).exists

    def wait_not_exists(self, timeout=15, **kwargs):
        """
        等待元素消失
        :param timeout: 超时时间
        :param kwargs: 元素定位
        :return:
        """
        num = 1
        while num <= timeout * 2:
            if self.exists(**kwargs):
                self.sleep(0.5)
                num = num + 1
            else:
                return True
        return False

    def exists_by_element(self, element, timeout=10):
        """
        判断元素是否存在
        :param element: 元素对象
        :param timeout: 超时时间
        :return:
        """
        return element.exists(timeout=timeout)

    def disable_popups(self, disable=True):
        """弹出窗口
        @:param disable True:自动跳过弹出窗口,False:禁用自动跳过弹出窗口
        """
        self.device.disable_popups(disable)

    def get_toast(self, wait_timeout=15,
                  cache_timeout=8,
                  default=None):
        """
        获取toast提示
        :param wait_timeout: 超时时间
        :param cache_timeout: 从现在开始多少时间以内
        :param default: 超时提示
        :return:
        """
        toast = self.device.toast.get_message(wait_timeout=wait_timeout,
                                              cache_timeout=cache_timeout,
                                              default=default)
        if toast:
            self.reset_toast()
        return toast

    def reset_toast(self):
        """
        清除设备toast提示
        :return:
        """
        self.device.toast.reset()