Skip to content

Commit

Permalink
add xpath::get_text(), close #337
Browse files Browse the repository at this point in the history
  • Loading branch information
codeskyblue committed May 6, 2019
1 parent 9d07fef commit aed0797
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 17 deletions.
16 changes: 9 additions & 7 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
**提Bug需要注意的事项**
**看完请删掉该内容**

尽可能详细的信息。For example:

- [ ] 版本号(`pip show uiautomator2`)
- [ ] 手机截图
- [ ] 相关日志
- [ ] 最好能附上可能复现问题的代码。
>*提Bug需要注意的事项*
>
>尽可能详细的信息。For example:
>
>- 版本号(`pip show uiautomator2`)
>- 手机截图
>- 相关日志
>- 最好能附上可能复现问题的代码。
15 changes: 15 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# coding: utf-8

import uiautomator2 as u2
import pytest


@pytest.fixture(scope="module")
def d():
return u2.connect()


@pytest.fixture(scope="function")
def sess(d) -> u2.Session:
with d.session("io.appium.android.apis") as s:
yield s
24 changes: 24 additions & 0 deletions tests/test_xpath.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# coding: utf-8
#

import uiautomator2 as u2
import pytest

# def setup_function():


def test_get_text(sess: u2.Session):
assert sess.xpath("App").get_text() == "App"


def test_click(sess: u2.Session):
sess.xpath("App").click()
assert sess.xpath("Alarm").wait()
assert sess.xpath("Alarm").exists


def test_all(sess: u2.Session):
app = sess.xpath('//*[@text="App"]')
assert app.wait()
assert len(app.all()) == 1
assert app.exists
4 changes: 4 additions & 0 deletions uiautomator2/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ class ConnectError(UiaError):
pass


class XPathElementNotFoundError(UiaError):
pass


class GatewayError(UiaError):
def __init__(self, response, description):
self.response = response
Expand Down
46 changes: 36 additions & 10 deletions uiautomator2/ext/xpath/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
#

import re
import time
import threading
import time

import uiautomator2
from uiautomator2.utils import U
from logzero import logger
from lxml import etree

import uiautomator2
from uiautomator2.exceptions import XPathElementNotFoundError
from uiautomator2.utils import U


def safe_xmlstr(s):
return s.replace("$", "-")
Expand Down Expand Up @@ -46,11 +48,11 @@ def __init__(self, d):
self._alias = {}
self._alias_strict = False

def global_set(self, key, value): #dicts):
def global_set(self, key, value): #dicts):
valid_keys = {"timeout", "alias", "alias_strict"}
if key not in valid_keys:
raise ValueError("invalid key", key)
setattr(self, "_"+key, value)
setattr(self, "_" + key, value)
# for k, v in dicts.items():
# if k not in valid_keys:
# raise ValueError("invalid key", k)
Expand Down Expand Up @@ -117,6 +119,10 @@ def sleep_watch(self, seconds):
time.sleep(min(0.5, left_time))

def click(self, xpath, source=None, watch=True, timeout=None):
"""
Raises:
TimeoutException
"""
timeout = timeout or self._timeout
logger.info("XPath(timeout %.1f) %s", timeout, xpath)

Expand Down Expand Up @@ -154,7 +160,7 @@ def __call__(self, xpath, source=None):
xpath = '//*[@resource-id={}]'.format(string_quote(xpath[1:]))
elif xpath.startswith('^'):
xpath = '//*[re:match(text(), {})]'.format(string_quote(xpath))
elif xpath.startswith("$"): # special for objects
elif xpath.startswith("$"): # special for objects
key = xpath[1:]
return self(self.__alias_get(key), source)
elif xpath.startswith('%') and xpath.endswith("%"):
Expand All @@ -175,14 +181,21 @@ def __init__(self, parent, xpath, source=None):
self._d = parent._d
self._xpath = xpath
self._source = source
self._last_source = None
self._watchers = []

def all(self):
@property
def _global_timeout(self):
return self._parent._timeout

def all(self, source=None):
"""
Returns:
list of XMLElement
"""
xml_content = self._source or self._d.dump_hierarchy()
xml_content = source or self._source or self._d.dump_hierarchy()
self._last_source = xml_content

root = etree.fromstring(xml_content.encode('utf-8'))
for node in root.xpath("//node"):
node.tag = safe_xmlstr(node.attrib.pop("class"))
Expand All @@ -195,6 +208,20 @@ def all(self):
def exists(self):
return len(self.all()) > 0

def get_text(self):
"""
get element text
Returns:
string of node text
Raises:
XPathElementNotFoundError
"""
if not self.wait(self._global_timeout):
raise XPathElementNotFoundError(self._xpath)
return self.all(self._last_source)[0].attrib.get("text", "")

def wait(self, timeout=None):
"""
Args:
Expand All @@ -203,7 +230,7 @@ def wait(self, timeout=None):
Raises:
bool of exists
"""
deadline = time.time() + (timeout or self._parent._timeout)
deadline = time.time() + (timeout or self._global_timeout)
while time.time() < deadline:
if self.exists:
return True
Expand Down Expand Up @@ -264,7 +291,6 @@ def attrib(self):
# def __repr__(self):
# return str(bool(self))


if __name__ == "__main__":
init()
import uiautomator2.ext.htmlreport as htmlreport
Expand Down

0 comments on commit aed0797

Please sign in to comment.