wda-driver
中文版
Facebook WebDriverAgent Node Client Library (not official)
Most functions finished.
Installation
- You need to start WebDriverAgent by yourself
Follow the instructions in https://github.com/facebook/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
- Install wda-driver client
npm install --save wda-driver
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]
Configuration
const wda = require('wda-driver')
How to use
Create a client
const wda = require('wda-driver')
const c = new wda.Client('http://localhost:8100')
c = wda.Client()
Client
console.log(await c.status())
await c.home()
await c.healthcheck()
const source = await c.source()
const source = await c.source(null, true)
Take screenshot, only can save format png, if params is empty, it will return base64 buffer
await c.screenshot('screen.png')
Get information about the current app
await c.getActiveAppInfo();
do actions chain
const actions = [
{
action: 'tap',
options: {
x: 300,
y: 100
}
},
{
action: 'wait',
options: {
ms: 700
}
},
{
action: 'tap',
options: {
x: 300,
y: 100
}
}
];
await session.chainOperation(actions);
Determine if the device is locked
await c.isLocked();
Open app
const s = await c.session('com.apple.Health')
console.log(await s.orientation())
await s.close()
For web browser like Safari you can define page whit which will be opened:
const s = await c.session('com.apple.mobilesafari', ['-u', 'https://www.google.com/ncr'])
console.log(await s.orientation())
await s.close()
Session operations
console.log(s.getId(), s.getBundleId())
console.log(await s.orientation())
await s.orientation(orientation)
await s.deactivate(5)
console.log(await s.getWindowSize())
await s.tap(88, 200)
await s.doubleTap(200, 200)
await s.swipe(x1, y1, x2, y2, 0.5)
await s.swipeLeft()
await s.swipeRight()
await s.swipeUp()
await s.swipeDown()
await s.tapHold(x, y, 1.0)
Find element
const selector = s.selector({id: "URL"})
await selector.exists()
s.selector({id: 'URL'})
s.selector({name: 'URL'})
s.selector({text: "URL"})
s.selector({nameContains: 'UR'})
s.selector({label: 'Address'})
s.selector({labelContains: 'Addr'})
s.selector({name:'URL', index: 1}) # find the second element. index starts from 0
s.selector({className: 'Button', name: 'URL', visible: true, labelContains: "Addr"})
More powerful findding method
s.selector({xpath: '//Button[@name="URL"]'})
s.selector({classChain: '**/Button[`name == "URL"`]'})
s.selector({predicate: 'name LIKE "UR*"'})
Element operations (eg: tap
, scroll
, set_text
etc...)
Exmaple search element and tap
const e = await s.selector({text: 'Dashboard'}).get(10)
await e.tap()
Click element if exists
await s.selector({text: 'Dashboard'}).clickExists()
await s.selector({text: 'Dashboard'}).clickExists(5)
Other Element operations
console.log(await s.selector({text: 'Dashboard'}).exists())
await s.selector({className: 'Other'}).findElements()
await s.selector({className: 'Other', index: 2}).exists()
await s.selector({text: 'Dashboard'}).child({className: 'Cell'}).exists()
s.setTimeout(50)
await e.tap()
await e.click()
await e.clearText()
await e.setText("Hello world")
await e.tapHold(2)
await e.scroll()
await e.scroll('up', 100)
await e.setText("Hello WDA")
await e.setText("Hello WDA\n")
await e.setText("\b\b\b")
await s({className: 'Other'}).waitGone(10)
s(className="Map").pinch(2, 1)
s(className="Map").pinch(0.1, -1)
await e.getAccessible()
await e.getDisplayed()
await e.getEnabled()
await e.getVisible()
await e.getAccessibilityContainer()
await e.getId()
await e.getLabel()
await e.getClassName()
await e.getText()
await e.getName()
await e.getDisplayed()
await e.getEnabled()
await e.getValue()
await e.getValue()
const rect = await e.getBounds()
rect.y
Alert
console.log(await s.alert().exists())
console.log(await s.alert().text())
console.log(await s.alert().text())
await s.alert().accept()
await s.alert().dismiss()
await s.alert().wait(5)
await s.alert().wait()
await s.alert().buttons()
await s.alert().click('好')
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
Reference
This project is a transplant by https://github.com/openatx/facebook-wda
Source code
DESIGN
DESIGN
LICENSE
MIT