UNPKG

wda-driver

Version:

Facebook WebDriverAgent Node Client Library (not official)

332 lines (246 loc) 9.28 kB
# wda-driver Facebook WebDriverAgent Node Client Library (not official) This project is a transplant of this project https://github.com/openatx/facebook-wda Most functions finished. ## Installation 1. 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 ``` 2. 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 ```javascript const wda = require('wda-driver') ``` ## How to use ### Create a client ```javascript const wda = require('wda-driver') const c = new wda.Client('http://localhost:8100') // http://localhost:8100 is the default value if $DEVICE_URL is empty c = wda.Client() ``` ### Client ```javascript // Show status console.log(await c.status()) // Press home button await c.home() // Hit healthcheck await c.healthcheck() // Get page source // format (str): only 'xml' and 'json' source types are supported // accessible (bool): when set to true, format is always 'json' const source = await c.source() // format XML const source = await c.source(null, true) // default false, format JSON ``` Take screenshot, only can save format png ```javascript await c.screenshot('screen.png') ``` Open app ```javascript 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: ```javascript const s = await c.session('com.apple.mobilesafari', ['-u', 'https://www.google.com/ncr']) console.log(await s.orientation()) await s.close() ``` ### Session operations ```javascript // Current bundleId and sessionId console.log(s.getId(), s.getBundleId()) // One of <PORTRAIT | LANDSCAPE> console.log(await s.orientation()) // expect PORTRAIT // Change orientation // LANDSCAPE | PORTRAIT | UIA_DEVICE_ORIENTATION_LANDSCAPERIGHT |UIA_DEVICE_ORIENTATION_PORTRAIT_UPSIDEDOWN await s.orientation(orientation) // Deactivate App for some time await s.deactivate(5) // 5s // Get width and height console.log(await s.getWindowSize()) // Expect json output // For example: {'height': 736, 'width': 414} // Simulate touch await s.tap(88, 200) // Double touch await s.doubleTap(200, 200) // Simulate swipe, utilizing drag api await s.swipe(x1, y1, x2, y2, 0.5) // 0.5s await s.swipeLeft() await s.swipeRight() await s.swipeUp() await s.swipeDown() // tap hold await s.tapHold(x, y, 1.0) ``` ### Find element > Note: if element not found, will throw error ```javascript // For example, expect: true or false // using id to find element and check if exists const selector = s.selector({id: "URL"}) await selector.exists() // return true or false // using id or other query conditions s.selector({id: 'URL'}) s.selector({name: 'URL'}) s.selector({text: "URL"}) // text is alias of name 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 // combines search conditions // attributes bellow can combines // :"className", "name", "label", "visible", "enabled" s.selector({className: 'Button', name: 'URL', visible: true, labelContains: "Addr"}) ``` More powerful findding method ```javascript 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 ```javascript // Get first match Element object // The function get() is very important.it will return an Element object // when elements founded in 10 seconds(:default:), Element object returns const e = await s.selector({text: 'Dashboard'}).get(10) // e is elements object await e.tap() // tap element ``` Click element if exists ```javascript await s.selector({text: 'Dashboard'}).clickExists() // return immediately if not found await s.selector({text: 'Dashboard'}).clickExists(50) // wait for 5s ``` Other Element operations ```javascript // Check if elements exists console.log(await s.selector({text: 'Dashboard'}).exists()) // Find all matches elements, return Array of Element object await s.selector({className: 'Other'}).findElements() // Use index to find second element await s.selector({className: 'Other', index: 2}).exists() // Use child to search sub elements await s.selector({text: 'Dashboard'}).child({className: 'Cell'}).exists() // Default timeout is 10 seconds // But you can change by s.setTimeout(100000) // do element operations await e.tap() await e.click() // alias of tap // The default keyboard must be requested await e.clearText() await e.setText("Hello world") await e.tapHold(2) // tapAndHold for 2.0s await 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 await e.scroll('up', 100) // Set text await e.setText("Hello WDA") // normal usage await e.setText("Hello WDA\n") // send text with enter await e.setText("\b\b\b") // delete 3 chars // Wait element gone await s({className: 'Other'}).waitGone(10) // Swipe TODO // 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) await e.getAccessible() await e.getDisplayed() await e.getEnabled() await e.getVisible() await e.getAccessibilityContainer() // properties (str) 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() // Bounds return namedtuple const rect = await e.getBounds() // Rect { x: 0, y: 73, width: 375, height: 666 } rect.y // 73 ``` Alert ```javascript console.log(await s.alert().exists()) console.log(await s.alert().text()) console.log(await s.alert().text()) await s.alert().accept() // Actually do click first alert button await s.alert().dismiss() // Actually do click second alert button await s.alert().wait(5) // if alert apper in 5 second it will return true,else return false (default 20.0) await s.alert().wait() // wait alert apper in 20 second await s.alert().buttons() // example return: ["设置", "好"] 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 ```sh $ ideviceinstaller -l ``` ## Reference Source code - [Router](https://github.com/facebook/WebDriverAgent/blob/master/WebDriverAgentLib/Commands/FBElementCommands.m#L62) - [Alert](https://github.com/facebook/WebDriverAgent/blob/master/WebDriverAgentLib/Commands/FBAlertViewCommands.m#L25) ## DESIGN [DESIGN](DESIGN.md) ## LICENSE [MIT](LICENSE)