Coder Social home page Coder Social logo

facebook-wda's Introduction

python-wda

Build Status PyPI PyPI

Facebook WebDriverAgent Python Client Library (not official) Implemented apis describe in https://github.com/facebook/WebDriverAgent/wiki/Queries

Most functions finished.

Since facebook/WebDriverAgent has been archived. Recommend use the forked WDA: https://github.com/appium/WebDriverAgent

Tested with: https://github.com/appium/WebDriverAgent/tree/v2.16.1

Alternatives

Installation

  1. You need to start WebDriverAgent by yourself

    New There is a new tool, which can start WDA without xcodebuild, even you can run in Linux and Windows. See: https://github.com/alibaba/tidevice

    Or

    Follow the instructions in https://github.com/appium/WebDriverAgent

    It is better to start with Xcode to prevent CodeSign issues.

    But it is also ok to start WDA with command line.

    xcodebuild -project WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination 'platform=iOS Simulator,name=iPhone 6' test
    

    WDA在真机上运行需要一些配置,可以参考这篇文章 ATX 文档 - iOS 真机如何安装 WebDriverAgent

    配置完之后运行下面的命令即可(需要用到Mac的密码,以及设备的UDID)

    # 解锁keychain,以便可以正常的签名应用
    security unlock-keychain -p $your-mac-password-here ~/Library/Keychains/login.keychain
    
    # 获取设备的UDID
    UDID=$(idevice_id -l | head -n1)
    
    # 运行测试
    xcodebuild -project WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination "id=$UDID" test
  2. Install python wda client

    pip3 install -U facebook-wda
    

TCP connection over USB (optional)

You can use wifi network, it is very convinient, but not very stable enough.

I found a tools named iproxy which can forward device port to localhost, it's source code is here https://github.com/libimobiledevice/libusbmuxd

The usage is very simple iproxy <local port> <remote port> [udid]

For more information see SSH Over USB

Something you need to know

function window_size() return UIKit size, While screenshot() image size is Native Resolution

IOS Display

when use screenshot, the image size is pixels size. eg(1080 x 1920) But this size is different with c.window_size()

use session.scale to get UIKit scale factor

Configuration

import wda

wda.DEBUG = False # default False
wda.HTTP_TIMEOUT = 60.0 # default 60.0 seconds

How to use

Create a client

import wda

# Enable debug will see http Request and Response
# wda.DEBUG = True
c = wda.Client('http://localhost:8100')

# get env from $DEVICE_URL if no arguments pass to wda.Client
# http://localhost:8100 is the default value if $DEVICE_URL is empty
c = wda.Client()

A wda.WDAError will be raised if communite with WDA went wrong.

Experiment feature: create through usbmuxd without iproxy

Added in version: 0.9.0

class USBClient inherit from Client

USBClient connect to wda-server through unix:/var/run/usbmuxd

import wda

# 如果只有一个设备也可以简写为
# If there is only one iPhone connecttd
c = wda.USBClient()

# 支持指定设备的udid,和WDA的端口号
# Specify udid and WDA port
c = wda.USBClient("539c5fffb18f2be0bf7f771d68f7c327fb68d2d9", port=8100)

# 也支持通过DEVICE_URL访问
c = wda.Client("usbmux://{udid}:8100".format(udid="539c5fffb18f2be0bf7f771d68f7c327fb68d2d9"))
print(c.window_size())

# 注:
# 仅在安装了tins的电脑上可以使用(目前并不对外开放)
# 1.2.0 引入 wda_bundle_id 参数
c = wda.USBClient("539c5fffb18f2be0bf7f771d68f7c327fb68d2d9", port=8100, wda_bundle_id="com.facebook.custom.xctest")

看到这里,可以看 examples 目录下的一些代码了

Client

# Show status
print c.status()

# Wait WDA ready
c.wait_ready(timeout=300) # 等待300s,默认120s
c.wait_ready(timeout=300, noprint=True) # 安静的等待,无进度输出

# Press home button
c.home()

# Hit healthcheck
c.healthcheck()

# Get page source
c.source() # format XML
c.source(accessible=True) # default false, format JSON

c.locked() # true of false
c.lock() # lock screen
c.unlock() # unlock
c.app_current() # {"pid": 1281, "bundleId": "com.netease.cloudmusic"}

# OpenURL not working very well
c.open_url("taobao://m.taobao.com/index.htm")

Take screenshot save as png

c.screenshot('screen.png') # Good
c.screenshot("screen.jpg") # Bad

# convert to PIL.Image and then save as jpg
c.screenshot().save("screen.jpg") # Good

c.appium_settings() # 获取appium的配置
c.appium_settings({"mjpegServerFramerate": 20}) # 修改配置

Session

From version 0.7.0, All Session methods moved to Client class. now Session is alias of Client

Open app

with c.session('com.apple.Health') as s:
	print(s.orientation)

Same as

s = c.session('com.apple.Health')
print(s.orientation)
s.close()

For web browser like Safari you can define page whit which will be opened:

s = c.session('com.apple.mobilesafari', ['-u', 'https://www.google.com/ncr'])
print(s.orientation)
s.close()

Other app operation (Works in appium/WebDriverAgent)

c.app_current() # show current app info
# Output example --
# {'processArguments': {'env': {}, 'args': []},
# 'name': '',
# 'pid': 2978,
# 'bundleId': 'com.apple.Preferences'}

# Handle alert automatically in WDA (never tested before)
# alert_action should be one of ["accept", "dismiss"]
s = c.session("com.apple.Health", alert_action="accept")

# launch without terminate app (WDAEmptyResponseError might raise)
c.session().app_activate("com.apple.Health") # same as app_launch

# terminate app
c.session().app_terminate("com.apple.Health")

# get app state
c.session().app_state("com.apple.Health")
# output {"value": 4, "sessionId": "xxxxxx"}
# different value means 1: die, 2: background, 4: running

Session operations

# set default element search timeout 30 seconds
s.implicitly_wait(30.0)

# Current bundleId and sessionId
print(s.bundle_id, s.id)

s.home() # same as c.home(), use the same API

s.lock() # lock screen
s.unlock() # unlock screen
s.locked() # locked status, true or false

s.battery_info() # return like {"level": 1, "state": 2}
s.device_info() # return like {"currentLocale": "zh_CN", "timeZone": "Asia/Shanghai"}

s.set_clipboard("Hello world") # update clipboard
# s.get_clipboard() # Not working now

# Screenshot return PIL.Image
# Requires pillow, installed by "pip install pillow"
s.screenshot().save("s.png")

# Sometimes screenshot rotation is wrong, but we can rotate it to the right direction
# Refs: https://pillow.readthedocs.io/en/3.1.x/reference/Image.html#PIL.Image.Image.transpose
from PIL import Image
s.screenshot().transpose(Image.ROTATE_90).save("correct.png")

# One of <PORTRAIT | LANDSCAPE>
print(s.orientation) # expect PORTRAIT or LANDSCAPE

# Change orientation
s.orientation = wda.LANDSCAPE # there are many other directions

# Deactivate App for some time
s.deactivate(5.0) # 5s

# Get width and height
print(s.window_size())
# Expect tuple output (width, height)
# For example: (414, 736)

# Get UIKit scale factor, the first time will take about 1s, next time use cached value
print(s.scale)
# Example output: 3

# Simulate touch
s.tap(200, 200)

# Very like tap, but support float and int argument
# float indicate percent. eg 0.5 means 50%
s.click(200, 200)
s.click(0.5, 0.5) # click center of screen
s.click(0.5, 200) # click center of x, and y(200)

# Double touch
s.double_tap(200, 200)

# Simulate swipe, utilizing drag api
s.swipe(x1, y1, x2, y2, 0.5) # 0.5s
s.swipe(0.5, 0.5, 0.5, 1.0)  # swipe middle to bottom

s.swipe_left()
s.swipe_right()
s.swipe_up()
s.swipe_down()

# tap hold for 1 seconds
s.tap_hold(x, y, 1.0)

# Hide keyboard (not working in simulator), did not success using latest WDA
# s.keyboard_dismiss()

# press home, volumeUp, volumeDown
s.press("home") # fater then s.home()
s.press("volumeUp")
s.press("volumeDown")

# New in WebDriverAgent(3.8.0)
# long press home, volumeUp, volumeDown, power, snapshot(power+home)
s.press_duration("volumeUp", 1) # long press for 1 second
s.press_duration("snapshot", 0.1)

Find element

Note: if element not found, WDAElementNotFoundError will be raised

# For example, expect: True or False
# using id to find element and check if exists
s(id="URL").exists # return True or False

# using id or other query conditions
s(id='URL')

# using className
s(className="Button")

# using name
s(name='URL')
s(nameContains='UR')
s(nameMatches=".RL")

# using label
s(label="label")
s(labelContains="URL")

# using value
s(value="Enter")
s(valueContains="RL")

# using  visible, enabled
s(visible=True, enabled=True)

# using index, index must combined with at least on label,value, etc...
s(name='URL', index=1) # find the second element. index of founded elements, min is 0

# combines search conditions
# attributes bellow can combines
# :"className", "name", "label", "visible", "enabled"
s(className='Button', name='URL', visible=True, labelContains="Addr")

More powerful finding method

s(xpath='//Button[@name="URL"]')

# another code style
s.xpath('//Button[@name="URL"]')

s(predicate='name LIKE "UR*"')
s('name LIKE "U*L"') # predicate is the first argument, without predicate= is ok
s(classChain='**/Button[`name == "URL"`]')

To see more Class Chain Queries examples, view https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules

Predicate Format String Syntax

Get Element info

# if not found, raise WDAElementNotFoundError
e = s(text='Dashboard').get(timeout=10.0)

# e could be None if not exists
e = s(text='Dashboard').wait(timeout=10.0)

# get element attributes
e.className # XCUIElementTypeStaticText
e.name # XCUIElementTypeStaticText  /name
e.visible # True    /attribute/visible
e.value # Dashboard /attribute/value
e.label # Dashboard /attribute/label
e.text # Dashboard  /text
e.enabled # True    /enabled
e.displayed # True  /displayed

e.bounds # Rect(x=161, y=32, width=53, height=21)  /rect
x, y, w, h = e.bounds

Element operations (eg: tap, scroll, set_text etc...)

Exmaple search element and tap

# Get first match Element object
# The function get() is very important.
# when elements founded in 10 seconds(:default:), Element object returns
# or WDAElementNotFoundError raises
e = s(text='Dashboard').get(timeout=10.0)
# s(text='Dashboard') is Selector
# e is Element object
e.tap() # tap element

Some times, I just hate to type .get()

Using python magic tricks to do it again.

# 	using python magic function "__getattr__", it is ok with out type "get()"
s(text='Dashboard').tap()
# same as
s(text='Dashboard').get().tap()

Note: Python magic tricks can not used on get attributes

# Accessing attrbutes, you have to use get()
s(text='Dashboard').get().value

# Not right
# s(text='Dashboard').value # Bad, always return None

Click element if exists

s(text='Dashboard').click_exists() # return immediately if not found
s(text='Dashboard').click_exists(timeout=5.0) # wait for 5s

Other Element operations

# Check if elements exists
print(s(text="Dashboard").exists)

# Find all matches elements, return Array of Element object
s(text='Dashboard').find_elements()

# Use index to find second element
s(text='Dashboard')[1].exists

# Use child to search sub elements
s(text='Dashboard').child(className='Cell').exists

# Default timeout is 10 seconds
# But you can change by
s.set_timeout(10.0)

# do element operations
e.tap()
e.click() # alias of tap
e.clear_text()
e.set_text("Hello world")
e.tap_hold(2.0) # tapAndHold for 2.0s

e.scroll() # scroll to make element visiable

# directions can be "up", "down", "left", "right"
# swipe distance default to its height or width according to the direction
e.scroll('up')

# Set text
e.set_text("Hello WDA") # normal usage
e.set_text("Hello WDA\n") # send text with enter
e.set_text("\b\b\b") # delete 3 chars

# Wait element gone
s(text='Dashboard').wait_gone(timeout=10.0)

# Swipe
s(className="Image").swipe("left")

# Pinch
s(className="Map").pinch(2, 1) # scale=2, speed=1
s(className="Map").pinch(0.1, -1) # scale=0.1, speed=-1 (I donot very understand too)

# properties (bool)
e.accessible
e.displayed
e.enabled

# properties (str)
e.text # ex: Dashboard
e.className # ex: XCUIElementTypeStaticText
e.value # ex: github.com

# Bounds return namedtuple
rect = e.bounds # ex: Rect(x=144, y=28, width=88.0, height=27.0)
rect.x # expect 144

Alert

print(s.alert.exists)
print(s.alert.text)
s.alert.accept() # Actually do click first alert button
s.alert.dismiss() # Actually do click second alert button
s.alert.wait(5) # if alert apper in 5 second it will return True,else return False (default 20.0)
s.alert.wait() # wait alert apper in 2 second

s.alert.buttons()
# example return: ["设置", "好"]

s.alert.click("设置")
s.alert.click(["设置", "信任", "安装"]) # when Arg type is list, click the first match, raise ValueError if no match

Alert monitor

with c.alert.watch_and_click(['好', '确定']):
	s(label="Settings").click() # 
	# ... other operations

# default watch buttons are
# ["使用App时允许", "好", "稍后", "稍后提醒", "确定", "允许", "以后"]
with c.alert.watch_and_click(interval=2.0): # default check every 2.0s
	# ... operations

Callback

回调操作: register_callback

c = wda.Client()

# 使用Example
def device_offline_callback(client, err):
	if isinstance(err, (requests.ConnectionError, wda.WDABadGateway, requests.ReadTimeout)):
		print("Handle device offline")
		ok = client.wait_ready(60) # 等待60s恢复
		if not ok:
			return wda.Callback.RET_ABORT
		return wda.Callback.RET_RETRY

c.register_callback(wda.Callback.ERROR, device_offline_callback, try_first=True)
# try_first 优先使用device_offline_callback函数处理ERROR


# the argument name in callback function can be one of
# - client: wda.Client
# - url: str, eg: http://localhost:8100/session/024A4577-2105-4E0C-9623-D683CDF9707E/wda/keys
# - urlpath: str, eg: /wda/keys  (without session id)
# - with_session: bool # if url contains session id
# - method: str, eg: GET
# - response: dict # Callback.HTTP_REQUEST_AFTER only 
# - err: WDAError # Callback.ERROR only
#
def _cb(client: wda.Client, url: str):
	if url.endswith("/wda/keys"):
		print("send_keys called")

c.register_callback(wda.Callback.HTTP_REQUEST_BEFORE, _cb)
c.register_callback(wda.Callback.HTTP_REQUEST_BEFORE, lambda url: print(url), try_first=True) # 回调会比_cb更先回调
c.send_keys("Hello")

# unregister
c.unregister_callback(wda.Callback.HTTP_REQUEST_BEFORE, _cb)
c.unregister_callback(wda.Callback.HTTP_REQUEST_BEFORE) # ungister all
c.unregister_callback() # unregister all callbacks

支持的回调有

wda.Callback.HTTP_REQUEST_BEFORE
wda.Callback.HTTP_REQUEST_AFTER
wda.Callback.ERROR

默认代码内置了两个回调函数 wda.Callback.ERROR,使用c.unregister_callback(wda.Callback.ERROR)可以去掉这两个回调

  • 当遇到invalid session id错误时,更新session id并重试
  • 当遇到设备掉线时,等待wda.DEVICE_WAIT_TIMEOUT时间 (当前是30s,以后可能会改的更长一些)

TODO

longTap not done pinch(not found in WDA)

TouchID

  • Match Touch ID
  • Do not match Touch ID

How to handle alert message automaticly (need more tests)

For example

import wda

s = wda.Client().session()

def _alert_callback(session):
    session.alert.accept()

s.set_alert_callback(_alert_callback) # deprecated,此方法不能用了

# do operations, when alert popup, it will auto accept
s(type="Button").click()

Special property

# s: wda.Session
s.alibaba.xxx # only used in alibaba-company

DEVELOP

See DEVELOP.md for more details.

iOS Build-in Apps

苹果自带应用

Name Bundle ID
iMovie com.apple.iMovie
Apple Store com.apple.AppStore
Weather com.apple.weather
相机Camera com.apple.camera
iBooks com.apple.iBooks
Health com.apple.Health
Settings com.apple.Preferences
Watch com.apple.Bridge
Maps com.apple.Maps
Game Center com.apple.gamecenter
Wallet com.apple.Passbook
电话 com.apple.mobilephone
备忘录 com.apple.mobilenotes
指南针 com.apple.compass
浏览器 com.apple.mobilesafari
日历 com.apple.mobilecal
信息 com.apple.MobileSMS
时钟 com.apple.mobiletimer
照片 com.apple.mobileslideshow
提醒事项 com.apple.reminders
Desktop com.apple.springboard (Start this will cause your iPhone reboot)

第三方应用 Thirdparty

Name Bundle ID
腾讯QQ com.tencent.mqq
微信 com.tencent.xin
部落冲突 com.supercell.magic
钉钉 com.laiwang.DingTalk
Skype com.skype.tomskype
Chrome com.google.chrome.ios

Another way to list apps installed on you phone is use ideviceinstaller install with brew install ideviceinstaller

List apps with command

$ ideviceinstaller -l

Tests

测试的用例放在tests/目录下,使用iphone SE作为测试机型,系统语言应用。调度框架pytest

WDA Benchmark E2E Tests

E2E Tests Latest WDA Version Testing Report:

Reference

Source code

Thanks

Articles

Contributors

DESIGN

DESIGN

LICENSE

MIT

facebook-wda's People

Contributors

codeskyblue avatar crevetor avatar diaojunxian avatar doublehyh avatar iquicktest avatar lpe234 avatar lukzeg avatar luze-mobica avatar riccoyu avatar senosoft2009 avatar wwjackli avatar youngfreefjs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

facebook-wda's Issues

tap method has a bug

Hi,

I found that when I use wda_session.tap(x, y) method on my iPad, there is a 50% difference.

For example, if I want to tap (100, 200) on my iPad screen, I have to use wda_session.tap(50, 100).

I have to add a new function to my code like this:

def click(wda_session, x, y):
	'''
	wda has a bug
	'''
	wda_session.tap(x//2, y//2)

横屏tap点击出现了一些问题

环境

机型:iPhone 7
系统版本:11.2.1
显示宽度:375
显示高度:667
(横屏相反)

问题描述

在横屏状态下LANDSCAPE_RIGHTLANDSCAPE,当i值出现大于等于750时,就会出现点击错位的问题

代码如下

import wda

client = wda.Client()
session = client.session()
session.orientation = wda.LANDSCAPE


def tap(x, y):
    session.tap_hold(x / 2, y / 2, 0.1)


def main():
    for v in range(100, 500, 100):
        for i in range(100, 1300, 100):
            tap(v, i)
            # 当`i`值出现大于等于750时,就会出现点击错位的问题


if __name__ == "__main__":
    main()

错误截图

我尝试在备忘录中重现Bug状态,请参考以下截图

LANDSCAPE模式下的点击截图
LANDSCAPE模式下的点击截图

LANDSCAPE_RIGHT模式下的点击截图
LANDSCAPE_RIGHT模式下的点击截图

ios真机上 在有些app上运行某些函数,会出现 requests.exceptions.ReadTimeout: HTTPConnectionPool(host='localhost', port=8100): Read timed out. (read timeout=60.0) 这样的报错

  1. 在某些ios第三方app上, 通过自己编写的py脚本调用这个函数 print driver.source() , 打印页面的数据结构的时候, 如下图所示:
    4201562124736_ pic_hd

报如下的错误 : requests.exceptions.ReadTimeout: HTTPConnectionPool(host='localhost', port=8100): Read timed out. (read timeout=60.0)

  1. 而且我发现当通过py脚本打印页面数据结构的报错的时候。 我重新Product -> Test 重新启动WebDriverAgentRunner, 然后Safari
    通过网页 localhost:8100/inspector ( 我已经通过 tcprelay.py -t 8100:8100 端口转发了 ), 也是发现页面进不去的 , 好像也是得不到页面的数据结构, 导致页面进不去似的

  2. 但是我发现我把手机网络断掉 , 上面的1,2 我阐述的问题 都解决了, print driver.source() 能够打印数据结构, 也能Safari 通过网页 localhost:8100/inspector 进去看到页面, 但是我手机开网络, 1,2 问题又会重现, 这是什么原因导致的呢? 希望大佬解惑下 感谢

我的猜想:

  1. 是不是因为在有网的时候, app自己本身有很多http请求, 导致会WebDriverAgent的http网络请求阻塞了呢

Add possibility to pass arguments to session

Hi,

Can we add also additional argument in the session, so we might to open Safari app with selected url?

s = client.session("localhost:8100","-u https://www.google.com/ncr")

As we know the arguments should be pass as list, but we can split this inside your code.
curl -X POST $JSON_HEADER \ -d "{\"desiredCapabilities\":{\"bundleId\":\"com.apple.mobilesafari\", \"arguments\":[\"-u\", \"https://www.google.com/ncr\"]}}" \ $DEVICE_URL/session

facebook/WebDriverAgent废弃了一批endpoint定义,这个工程需要对应的修改

春节前WebDriverAgent参照WD spec调整了接口url地址。直到最近,旧的接口url地址被废弃了 facebookarchive/WebDriverAgent@dccf5c8
此工程需要对应的修改

before after status
POST /homescreen POST /wda/homescreen done
POST /deactivateApp POST /wda/deactivateApp done
POST /source GET /source done
GET /window/:uuid/size GET /window/size done
POST /element/:uuid/pinch POST /wda/element/:uuid/pinch done
GET /element/:uuid/accessible GET /wda/element/:uuid/accessible done
GET /element/:uuid/accessibilityContainer GET /wda/element/:uuid/accessibilityContainer
POST /uiaElement/:uuid/doubleTap POST /wda/element/:uuid/doubleTap done
POST /uiaElement/:uuid/twoFingerTap POST /wda/element/:uuid/twoFingerTap
POST /uiaElement/:uuid/touchAndHold POST /wda/element/:uuid/touchAndHold done
POST /uiaElement/:uuid/scroll POST /wda/element/:uuid/scroll
POST /uiaTarget/:uuid/dragfromtoforduration POST /wda/element/:uuid/dragfromtoforduration not implemented
POST /tap/:uuid POST /wda/tap/:uuid done
POST /touchAndHold POST /wda/touchAndHold done
POST /doubleTap POST /wda/doubleTap done
POST /keys POST /wda/keys done
GET /uiaElement/:uuid/getVisibleCells GET /wda/element/:uuid/getVisibleCells
GET /healthcheck GET /wda/healthcheck done
POST /simulator/touch_id POST /wda/touch_id

可以支持长按home键吗?

你好,看到XCUICoordinate中func press(forDuration duration: TimeInterval)参数是有时间的,这边没找到长按home键的方法,是否或者可以支持长按home键吗?

home()方法报错

error:

GenericDict(value='Error Domain=com.facebook.WebDriverAgent Code=1 "Timeout waiting until SpringBoard is visible" UserInfo={NSLocalizedDescription=Timeout waiting until SpringBoard is visible}', sessionId='2337B533-0195-492A-BF51-411C70F69B91', status=13)

ios真机上运行的问题

Traceback (most recent call last):
File "/Users/fengxiaooyong/Documents/百度工作/脚本管理/otatest/iosota.py", line 14, in
s = c.session(bundle_id)
File "/Users/fengxiaooyong/Library/Python/2.7/lib/python/site-packages/wda/init.py", line 304, in session
res = self.http.post('session', data)
File "/Users/fengxiaooyong/Library/Python/2.7/lib/python/site-packages/wda/init.py", line 109, in fetch
return self._fetch_no_alert(method, url, data)
File "/Users/fengxiaooyong/Library/Python/2.7/lib/python/site-packages/wda/init.py", line 115, in _fetch_no_alert
return httpdo(target_url, method, data)
File "/Users/fengxiaooyong/Library/Python/2.7/lib/python/site-packages/wda/init.py", line 77, in httpdo
response = requests.request(method, url, data=data, timeout=HTTP_TIMEOUT)
File "/Users/fengxiaooyong/Library/Python/2.7/lib/python/site-packages/requests/api.py", line 60, in request
return session.request(method=method, url=url, **kwargs)
File "/Users/fengxiaooyong/Library/Python/2.7/lib/python/site-packages/requests/sessions.py", line 533, in request
resp = self.send(prep, **send_kwargs)
File "/Users/fengxiaooyong/Library/Python/2.7/lib/python/site-packages/requests/sessions.py", line 646, in send
r = adapter.send(request, **kwargs)
File "/Users/fengxiaooyong/Library/Python/2.7/lib/python/site-packages/requests/adapters.py", line 498, in send
raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', BadStatusLine("''",))

手机是iphone 6 plus 版本是12.3.1,Xcode是10.2.1,facebook-wda 0.2.3
在模拟器上运行没有问题,但是真机上运行就有问题
iproxy 8100 8100 使用的是这个代理 ,请教下大神们

TypeError: 'PngImageFile' does not have the buffer interface

python -m atx gui -s http://192.168.199.146:8100
2019-06-16 00:03:06.259 DEBUG [tkgui: 412] gui starting(scale: 0.5) ...
DEPRECATION WARNING: The system version of Tk is deprecated and may be removed in a future release. Please don't rely on it. Set TK_SILENCE_DEPRECATION=1 to suppress this warning.
Traceback (most recent call last):
File "/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 174, in _run_module_as_main
"main", fname, loader, pkg_name)
File "/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/usr/local/lib/python2.7/site-packages/atx/main.py", line 199, in
main()
File "/usr/local/lib/python2.7/site-packages/atx/main.py", line 195, in main
args.func(args)
File "/usr/local/lib/python2.7/site-packages/atx/main.py", line 49, in _inner
return inject(mod.main, pargs)
File "/usr/local/lib/python2.7/site-packages/atx/main.py", line 40, in inject
return func(*args)
File "/usr/local/lib/python2.7/site-packages/atx/cmds/tkgui.py", line 425, in main
gui = CropIDE('ATX GUI SN: %s' % serial, ratio=scale, device=d)
File "/usr/local/lib/python2.7/site-packages/atx/cmds/tkgui.py", line 98, in init
self._init_vars()
File "/usr/local/lib/python2.7/site-packages/atx/cmds/tkgui.py", line 159, in _init_vars
self.draw_image(self._device.screenshot())
File "/usr/local/lib/python2.7/site-packages/atx/drivers/mixin.py", line 62, in _inner
_retval = fn(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/atx/drivers/mixin.py", line 404, in screenshot
screen = self._take_screenshot()
File "/usr/local/lib/python2.7/site-packages/atx/drivers/ios_webdriveragent.py", line 174, in _take_screenshot
img = Image.open(BytesIO(raw_png))
TypeError: 'PngImageFile' does not have the buffer interface

retry to connect, error: ('Connection aborted.', ConnectionResetError(54, 'Connection reset by peer'))

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 601, in urlopen
chunked=chunked)
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 387, in _make_request
six.raise_from(e, None)
File "", line 2, in raise_from
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 383, in _make_request
httplib_response = conn.getresponse()
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1331, in getresponse
response.begin()
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 297, in begin
version, status, reason = self._read_status()
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 258, in _read_status
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 586, in readinto
return self._sock.recv_into(b)
ConnectionResetError: [Errno 54] Connection reset by peer

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/requests/adapters.py", line 440, in send
timeout=timeout
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 639, in urlopen
_stacktrace=sys.exc_info()[2])
File "/usr/local/lib/python3.6/site-packages/urllib3/util/retry.py", line 357, in increment
raise six.reraise(type(error), error, _stacktrace)
File "/usr/local/lib/python3.6/site-packages/urllib3/packages/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 601, in urlopen
chunked=chunked)
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 387, in _make_request
six.raise_from(e, None)
File "", line 2, in raise_from
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 383, in _make_request
httplib_response = conn.getresponse()
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1331, in getresponse
response.begin()
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 297, in begin
version, status, reason = self._read_status()
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 258, in _read_status
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 586, in readinto
return self._sock.recv_into(b)
urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionResetError(54, 'Connection reset by peer'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "main.py", line 197, in start_auto_operation
self.app_record_screen(self.click_file_path, self.config_path)
File "main.py", line 145, in app_record_screen
runner.run()
File "/Users/tian/Documents/test/app_runner.py", line 416, in run
self.after_run()
File "/Users/tian/Documents/test/app_runner.py", line 74, in after_run
super(appRunner, self).after_run()
File "/Users/tian/Documents/test/app_runner.py", line 429, in after_run
self.close_app()
File "/Users/tian/Documents/test/app_runner.py", line 136, in close_app
self.session.close()
File "/usr/local/lib/python3.6/site-packages/wda/init.py", line 473, in close
return self.http.delete('/')
File "/usr/local/lib/python3.6/site-packages/wda/init.py", line 101, in fetch
return self._fetch_no_alert(method, url, data)
File "/usr/local/lib/python3.6/site-packages/wda/init.py", line 107, in _fetch_no_alert
return httpdo(target_url, method, data)
File "/usr/local/lib/python3.6/site-packages/wda/init.py", line 75, in httpdo
response = requests.request(method, url, data=data, timeout=HTTP_TIMEOUT)
File "/usr/local/lib/python3.6/site-packages/requests/api.py", line 58, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/local/lib/python3.6/site-packages/requests/sessions.py", line 508, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/lib/python3.6/site-packages/requests/sessions.py", line 618, in send
r = adapter.send(request, **kwargs)
File "/usr/local/lib/python3.6/site-packages/requests/adapters.py", line 490, in send
raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(54, 'Connection reset by peer'))

INFO: 2018-06-13 12:08:19, filename:main.py, lineno:212, thread:140735604671360
/Users/tian/Documents/ios-blackbox/blackdata/app/video/头条_6.7.5_iPhone7P_WiFi_首页视频1.mov
ERROR: 2018-06-13 12:08:19, filename:main.py, lineno:297, thread:140735604671360
MainRunner config files occur an error,error message = Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 601, in urlopen
chunked=chunked)
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 387, in _make_request
six.raise_from(e, None)
File "", line 2, in raise_from
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 383, in _make_request
httplib_response = conn.getresponse()
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1331, in getresponse
response.begin()
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 297, in begin
version, status, reason = self._read_status()
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 258, in _read_status
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 586, in readinto
return self._sock.recv_into(b)
ConnectionResetError: [Errno 54] Connection reset by peer

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/requests/adapters.py", line 440, in send
timeout=timeout
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 639, in urlopen
_stacktrace=sys.exc_info()[2])
File "/usr/local/lib/python3.6/site-packages/urllib3/util/retry.py", line 357, in increment
raise six.reraise(type(error), error, _stacktrace)
File "/usr/local/lib/python3.6/site-packages/urllib3/packages/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 601, in urlopen
chunked=chunked)
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 387, in _make_request
six.raise_from(e, None)
File "", line 2, in raise_from
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 383, in _make_request
httplib_response = conn.getresponse()
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1331, in getresponse
response.begin()
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 297, in begin
version, status, reason = self._read_status()
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 258, in _read_status
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 586, in readinto
return self._sock.recv_into(b)
urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionResetError(54, 'Connection reset by peer'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "main.py", line 290, in traverse_config
runner.start_auto_operation()
File "main.py", line 197, in start_auto_operation
self.app_record_screen(self.click_file_path, self.config_path)
File "main.py", line 145, in app_record_screen
runner.run()
File "/Users/tian/Documents/test/app_runner.py", line 416, in run
self.after_run()
File "/Users/tian/Documents/test/app_runner.py", line 74, in after_run
super(appRunner, self).after_run()
File "/Users/tian/Documents/test/app_runner.py", line 429, in after_run
self.close_app()
File "/Users/tian/Documents/test/app_runner.py", line 136, in close_app
self.session.close()
File "/usr/local/lib/python3.6/site-packages/wda/init.py", line 473, in close
return self.http.delete('/')
File "/usr/local/lib/python3.6/site-packages/wda/init.py", line 101, in fetch
return self._fetch_no_alert(method, url, data)
File "/usr/local/lib/python3.6/site-packages/wda/init.py", line 107, in _fetch_no_alert
return httpdo(target_url, method, data)
File "/usr/local/lib/python3.6/site-packages/wda/init.py", line 75, in httpdo
response = requests.request(method, url, data=data, timeout=HTTP_TIMEOUT)
File "/usr/local/lib/python3.6/site-packages/requests/api.py", line 58, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/local/lib/python3.6/site-packages/requests/sessions.py", line 508, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/lib/python3.6/site-packages/requests/sessions.py", line 618, in send
r = adapter.send(request, **kwargs)
File "/usr/local/lib/python3.6/site-packages/requests/adapters.py", line 490, in send
raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(54, 'Connection reset by peer'))

经常在测试了一会之后,就出现这个错误。不知道是什么原因。

I am not able to click on the sibling element

Here is the page source. I have a page where I want to click on the button of a particular text For e.g I want to click on the button next to the text Jhon. But both the text Jhon and Lisa has the same button id.

<XCUIElementTypeStaticText type="XCUIElementTypeStaticText" value="Jhon " name="Jhon " label="Jhon " enabled="true" visible="true" x="70" y="73" width="241" height="21"/>
<XCUIElementTypeButton type="XCUIElementTypeButton" name="companion checkbox checked" label="companion checkbox checked" enabled="true" visible="true" x="329" y="79" width="29" height="28"/>
<XCUIElementTypeStaticText type="XCUIElementTypeStaticText" value="Lisa " name="Lisa " label="Lisa " enabled="true" visible="true" x="70" y="73" width="241" height="21"/>
<XCUIElementTypeButton type="XCUIElementTypeButton" name="companion checkbox checked" label="companion checkbox checked" enabled="true" visible="true" x="329" y="79" width="29" height="28"/>

hide_keyborad not work[RuntimeError: not pass tests, this method is not allowed to use]

我在试你给的ReadMe,隐藏键盘报这个错
Traceback (most recent call last):
File "ba.py", line 47, in
s.keyboard_dismiss()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/wda/init.py", line 465, in keyboard_dismiss
raise RuntimeError("not pass tests, this method is not allowed to use")
RuntimeError: not pass tests, this method is not allowed to use

pip install --pre facebook-wda , how to solve,thanks

admindeMacBook-Pro:~ admin$ pip install --pre facebook-wda
Collecting facebook-wda
Using cached facebook_wda-0.2.2.dev1-py2-none-any.whl
Requirement already satisfied: six in ./Library/Python/2.7/lib/python/site-packages (from facebook-wda)
Collecting requests>=2.9.1 (from facebook-wda)
Using cached requests-2.18.4-py2.py3-none-any.whl
Collecting idna<2.7,>=2.5 (from requests>=2.9.1->facebook-wda)
Using cached idna-2.6-py2.py3-none-any.whl
Collecting urllib3<1.23,>=1.21.1 (from requests>=2.9.1->facebook-wda)
Using cached urllib3-1.22-py2.py3-none-any.whl
Collecting certifi>=2017.4.17 (from requests>=2.9.1->facebook-wda)
Using cached certifi-2017.11.5-py2.py3-none-any.whl
Collecting chardet<3.1.0,>=3.0.2 (from requests>=2.9.1->facebook-wda)
Using cached chardet-3.0.4-py2.py3-none-any.whl
Installing collected packages: idna, urllib3, certifi, chardet, requests, facebook-wda
Exception:
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/pip/basecommand.py", line 215, in main
status = self.run(options, args)
File "/Library/Python/2.7/site-packages/pip/commands/install.py", line 342, in run
prefix=options.prefix_path,
File "/Library/Python/2.7/site-packages/pip/req/req_set.py", line 784, in install
**kwargs
File "/Library/Python/2.7/site-packages/pip/req/req_install.py", line 851, in install
self.move_wheel_files(self.source_dir, root=root, prefix=prefix)
File "/Library/Python/2.7/site-packages/pip/req/req_install.py", line 1064, in move_wheel_files
isolated=self.isolated,
File "/Library/Python/2.7/site-packages/pip/wheel.py", line 345, in move_wheel_files
clobber(source, lib_dir, True)
File "/Library/Python/2.7/site-packages/pip/wheel.py", line 316, in clobber
ensure_dir(destdir)
File "/Library/Python/2.7/site-packages/pip/utils/init.py", line 83, in ensure_dir
os.makedirs(path)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py", line 157, in makedirs
mkdir(name, mode)
OSError: [Errno 13] Permission denied: '/Library/Python/2.7/site-packages/idna'

session.window_size() return size different with client.screenshot

First very thanks this great work, i use this to control my ios device. now i must make a function like :

  1. screenshot
    2.compare a template img ( like button in current screenshot png) with screenshot png
    3.output template img's width & height in screenshot

my question is:

1.session.width & height is 1024 * 768
2.screenshot.width & height is 2048 * 1536
these two size is different so when i get template size, it not right at screen.( i guess session.tap is work with session.size. right?)

can you tell me how to make screenshot png with session.size or how to make tap method work with screenshot png axis ?

thanks!

操作alert时响应非常慢,还会报错

test_b.py retry to connect, error: HTTPConnectionPool(host='localhost', port=8100): Read timed out. (read timeout=60.0)

  s.alert.accept()

test_b.py:31:


/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/wda/init.py:508: in accept
return self.http.post('/alert/accept')
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/wda/init.py:101: in fetch
return self._fetch_no_alert(method, url, data)
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/wda/init.py:107: in _fetch_no_alert
return httpdo(target_url, method, data)


url = 'http://localhost:8100/session/BBBAA7CE-6EDB-4D3D-B1B9-CF09A4AADC29/alert/accept'
method = 'post', data = None

def httpdo(url, method='GET', data=None):
    """
    Do HTTP Request
    """
    start = time.time()
    if isinstance(data, dict):
        data = json.dumps(data)
    if DEBUG:
        print("Shell: curl -X {method} -d '{data}' '{url}'".format(method=method.upper(), data=data or '', url=url))

    try:
        response = requests.request(method, url, data=data, timeout=HTTP_TIMEOUT)
    except (requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout) as e:
        # retry again
        print('retry to connect, error: {}'.format(e))
        time.sleep(1.0)
        response = requests.request(method, url, data=data, timeout=HTTP_TIMEOUT)

    retjson = response.json()
    if DEBUG:
        ms = (time.time() - start) * 1000
        print('Return ({:.0f}ms): {}'.format(ms, json.dumps(retjson, indent=4)))
    r = convert(retjson)
    if r.status != 0:
      raise WDAError(r.status, r.value)

E wda.WDAError: WDAError(status=27, value={})

/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/wda/init.py:83: WDAError
------------------------------ Captured log call -------------------------------
connectionpool.py 214 INFO Starting new HTTP connection (1): localhost
connectionpool.py 401 DEBUG "POST /session/BBBAA7CE-6EDB-4D3D-B1B9-CF09A4AADC29/elements HTTP/1.1" 200 94
connectionpool.py 214 INFO Starting new HTTP connection (1): localhost
connectionpool.py 401 DEBUG "POST /session/BBBAA7CE-6EDB-4D3D-B1B9-CF09A4AADC29/elements HTTP/1.1" 200 94
connectionpool.py 214 INFO Starting new HTTP connection (1): localhost
connectionpool.py 401 DEBUG "POST /session/BBBAA7CE-6EDB-4D3D-B1B9-CF09A4AADC29/elements HTTP/1.1" 200 94
connectionpool.py 214 INFO Starting new HTTP connection (1): localhost
connectionpool.py 401 DEBUG "POST /session/BBBAA7CE-6EDB-4D3D-B1B9-CF09A4AADC29/elements HTTP/1.1" 200 94
connectionpool.py 214 INFO Starting new HTTP connection (1): localhost
connectionpool.py 401 DEBUG "POST /session/BBBAA7CE-6EDB-4D3D-B1B9-CF09A4AADC29/elements HTTP/1.1" 200 94
connectionpool.py 214 INFO Starting new HTTP connection (1): localhost
connectionpool.py 401 DEBUG "POST /session/BBBAA7CE-6EDB-4D3D-B1B9-CF09A4AADC29/elements HTTP/1.1" 200 94
connectionpool.py 214 INFO Starting new HTTP connection (1): localhost
connectionpool.py 401 DEBUG "POST /session/BBBAA7CE-6EDB-4D3D-B1B9-CF09A4AADC29/elements HTTP/1.1" 200 94
connectionpool.py 214 INFO Starting new HTTP connection (1): localhost
connectionpool.py 401 DEBUG "POST /session/BBBAA7CE-6EDB-4D3D-B1B9-CF09A4AADC29/elements HTTP/1.1" 200 162
connectionpool.py 214 INFO Starting new HTTP connection (1): localhost
connectionpool.py 401 DEBUG "POST /session/BBBAA7CE-6EDB-4D3D-B1B9-CF09A4AADC29/wda/tap/0 HTTP/1.1" 200 94
connectionpool.py 214 INFO Starting new HTTP connection (1): localhost
connectionpool.py 401 DEBUG "POST /session/BBBAA7CE-6EDB-4D3D-B1B9-CF09A4AADC29/wda/tap/0 HTTP/1.1" 200 94
connectionpool.py 214 INFO Starting new HTTP connection (1): localhost
connectionpool.py 214 INFO Starting new HTTP connection (1): localhost
connectionpool.py 401 DEBUG "POST /session/BBBAA7CE-6EDB-4D3D-B1B9-CF09A4AADC29/alert/accept HTTP/1.1" 200 95
=============================== warnings summary ===============================
None
passing a string to pytest.main() is deprecated, pass a list of arguments instead.

-- Docs: http://doc.pytest.org/en/latest/warnings.html
=============== 1 failed, 1 passed, 1 warnings in 93.43 seconds ================

Process finished with exit code 0

iOS 12 unrecognized selector

import wda
c = wda.Client()
c.screenshot()

出现:

WebDriverAgentRunner-Runner[6458:1441982] +[XCAXClient_iOS sharedClient]: unrecognized selector sent to class 0x102d43e50

response = fn(url, data=data, timeout=20) timeout弄成可自定义

timeout=20的时候,我的set_text到httpdo的时候报:
ReadTimeout: HTTPConnectionPool(host='localhost', port=5000): Read timed out. (read timeout=20)

我手动修改成50就可以了,这个能提供成吗:
def httpdo(url, method='GET', data=None,timeout=20):
response = fn(url, data=data, timeout=timeout)

set_text也要对应修改

Sessions' find_element_ids() method prepends a ** to my value name, which causes an error

This issue is specific to version 0.2.1, and doesnt appear in version 0.1.2

My code selects an element from the session, then uses one of the element methods on it:

wda.DEBUG=True
passwordField = self.session(className="SecureTextField")
passwordField.set_text(self.TEST_INPUT_DATA['PASSWORD'])

Yet, this element method throws an error because of a certain ** string that gets prepended to the value:

CHAIN: **/XCUIElementTypeSecureTextField
Shell: curl -X POST -d '{"using": "class chain", "value": "**/XCUIElementTypeSecureTextField"}' 'http://127.0.0.1:8100/session/0C84F47E-06E6-43BF-AFB9-E0C882FB5112/elements'
Return (58ms): {
    "status": 13, 
    "sessionId": "0C84F47E-06E6-43BF-AFB9-E0C882FB5112", 
    "value": "Cannot parse class chain query '**/XCUIElementTypeSecureTextField'. Unexpected character detected at position 2:\n**

Desired capability not provided

data = json.dumps({
'desiredCapabilities': capabilities
})
res = self.http.post('session', data)
httpclient = self.http.new_client('session/'+res.sessionId)

看了下代码后面 httpdo 应该是传给了 request 这样的话应该不需要 json.dumps 吧。

本地环境把这个 dumps 删掉之后可以创建 session 了,否则一只报错连接不上。

[ IOS ]通过下标定位元素存在问题

例如一个页面有多个Cell或Button/StaticText等属性元素,假设用d(className="Cell")进行定位。
用exists属性检查元素是否存在,d(className="Cell")[0].exists正常返回True,而d(className="Cell")[1].exists返回False,1以上目前都返回False

Max retries exceeded error.

我只运行了你的代码示例:
import wda
c = wda.Client('http://localhost:8100')

就报出了如下错误,不清楚是哪里出了问题
`retry to connect, error: HTTPConnectionPool(host='localhost', port=8100): Max retries exceeded with url: /status (Caused by Ne
wConnectionError('<urllib3.connection.HTTPConnection object at 0x108572908>: Failed to establish a new connection: [Errno 8] n
odename nor servname provided, or not known',))
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/urllib3/connection.py", line 141, in _new_conn
(self.host, self.port), self.timeout, **extra_kw)
File "/usr/local/lib/python3.6/site-packages/urllib3/util/connection.py", line 60, in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
File "/usr/local/Cellar/python3/3.6.4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 745, in getadd
rinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 8] nodename nor servname provided, or not known

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 601, in urlopen
chunked=chunked)
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 357, in _make_request
conn.request(method, url, **httplib_request_kw)
File "/usr/local/Cellar/python3/3.6.4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1239, in
request
self._send_request(method, url, body, headers, encode_chunked)
File "/usr/local/Cellar/python3/3.6.4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1285, in
_send_request
self.endheaders(body, encode_chunked=encode_chunked)
File "/usr/local/Cellar/python3/3.6.4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1234, inendheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/usr/local/Cellar/python3/3.6.4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1026, in_send_output
self.send(msg)
File "/usr/local/Cellar/python3/3.6.4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 964, in send
self.connect()
File "/usr/local/lib/python3.6/site-packages/urllib3/connection.py", line 166, in connect
conn = self._new_conn()
File "/usr/local/lib/python3.6/site-packages/urllib3/connection.py", line 150, in _new_conn
self, "Failed to establish a new connection: %s" % e)
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x108572908>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/requests/adapters.py", line 440, in send
timeout=timeout
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 639, in urlopen
_stacktrace=sys.exc_info()[2])
File "/usr/local/lib/python3.6/site-packages/urllib3/util/retry.py", line 388, in increment
raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8100): Max retries exceeded with url: /status (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x108572908>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known',))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/wda/init.py", line 70, in httpdo
response = requests.request(method, url, data=data, timeout=HTTP_TIMEOUT)
File "/usr/local/lib/python3.6/site-packages/requests/api.py", line 58, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/local/lib/python3.6/site-packages/requests/sessions.py", line 508, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/lib/python3.6/site-packages/requests/sessions.py", line 618, in send
r = adapter.send(request, **kwargs)
File "/usr/local/lib/python3.6/site-packages/requests/adapters.py", line 508, in send
raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8100): Max retries exceeded with url: /status (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x108572908>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known',))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/urllib3/connection.py", line 141, in _new_conn
(self.host, self.port), self.timeout, **extra_kw)
File "/usr/local/lib/python3.6/site-packages/urllib3/util/connection.py", line 60, in create_connection
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
File "/usr/local/Cellar/python3/3.6.4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 745, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 8] nodename nor servname provided, or not known

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 601, in urlopen
chunked=chunked)
File "/usr/local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 357, in _make_request
conn.request(method, url, **httplib_request_kw)
File "/usr/local/Cellar/python3/3.6.4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1239, inrequest
self._send_request(method, url, body, headers, encode_chunked)
File "/usr/local/Cellar/python3/3.6.4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1285, in_send_request
self.endheaders(body, encode_chunked=encode_chunked)
File "/usr/local/Cellar/python3/3.6.4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1234, inendheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/usr/local/Cellar/python3/3.6.4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1026, in_send_output
self.send(msg)
File "/usr/local/Cellar/python3/3.6.4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 964, in send
self.connect()
File "/usr/local/lib/python3.6/site-packages/urllib3/connection.py", line 166, in connect
conn = self._new_conn()
File "/usr/local/lib/python3.6/site-packages/urllib3/connection.py", line 150, in _new_conn
self, "Failed to establish a new connection: %s" % e)
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x10858c080>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known`

WDAError : class chain did not add escape character for ' or "

If we will will want to get objects with ' or " character we observe WDAError(status 13):
session(text="don't")

I think in line 600:
https://github.com/openatx/facebook-wda/blob/master/wda/__init__.py

It should be added some method which will add "" before ' or " to avoid of having issue with parsing when chain is created(line:672), as we might to catch situation:
"name == 'I don't want'"
which is causing mentioned by me error.
Tested on WebDriverAgent - a10768631110f4b7c2d7ca328a9f11186464ae35

Warning: prefer use className instead of class_name

class Session 的 __call__ 方法中会将 className 参数改为 class_name。class Selector __init__ 方法中当 class_name 参数不为空时会输出

Warning: prefer use className instead of class_name

结果就是只要用到 className 的时候不管用 className 还是 class_name 都会打印这条 Warning

ios端 获取不到指定位置元素

例如一个页面有多个Cell或Button/StaticText等属性元素,假设用s(className="Cell")进行定位。
用exists属性检查元素是否存在,s(className="Cell")[0].exists正常返回True,而s(className="Cell")[1].exists返回False,1以上目前都返回False
使用s(className='Cell', index=0).exists返回true
使用s(className='Cell', index=1).exists返回false
但是使用s(className='Cell', index=1).find_elements()能获取到15个元素

ios绑定bundle_id的问题

Traceback (most recent call last):
  File "atxOTA.py", line 20, in 
    s = c.session('com.apple.mobilesafari', ['-u', 'https://www.google.com/ncr'])
  File "/Users/fengxiaooyong/Library/Python/2.7/lib/python/site-packages/wda/init.py", line 302, in session
    res = self.http.post('session', data)
  File "/Users/fengxiaooyong/Library/Python/2.7/lib/python/site-packages/wda/init.py", line 107, in fetch
    return self._fetch_no_alert(method, url, data)
  File "/Users/fengxiaooyong/Library/Python/2.7/lib/python/site-packages/wda/init.py", line 113, in _fetch_no_alert
    return httpdo(target_url, method, data)
  File "/Users/fengxiaooyong/Library/Python/2.7/lib/python/site-packages/wda/init.py", line 89, in httpdo
    raise WDAError(r.status, r.value)
wda.WDAError: WDAError(status=13, value='bundleId' desired capability not provided)

我看了webdriver的接口,发现我们传过去的是个json,接口收不到
def httpdo(url, method='GET', data=None):
"""
Do HTTP Request
"""
start = time.time()
if DEBUG:
body = json.dumps(data)
print("Shell: curl -X {method} -d '{body}' '{url}'".format(method=method.upper(), body=body or '', url=url))

try:
    print(data)
    response = requests.request(method, url, data=data, timeout=HTTP_TIMEOUT)
except (requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout):
    # retry again
    # print('retry to connect, error: {}'.format(e))

    time.sleep(1.0)
    response = requests.request(method, url, data=data, timeout=HTTP_TIMEOUT)

if DEBUG:
    ms = (time.time() - start) * 1000
    print('Return ({:.0f}ms): {}'.format(ms, response.text))

response = requests.request(method, url, data=data, timeout=HTTP_TIMEOUT)
里面的json参数,改成data就可以正常的工作了

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.