## 使用 WebDriverAgent/XCTest Backend 進行iOS自動化手勢操作
很可惜,蘋果官方的 XCTest 框架本身并不支持 TouchAction 接口實現的 W3C 標準。盡管如此,XCTest 提供了非常豐富的手勢操作,這些操作都是 iOS 平臺獨有的。你可以在 1.6.4-beta 版本的 Appium 中開始使用這些手勢操作。
需要特別注意的是目前XCTest和WDA正在不斷優化改變的階段,這意味著所有 `mobile: *` 的命令可能會在沒任何通知的情況下就被調整更改。
### mobile: swipe
這個手勢是在指定的屏幕上的控件或App的控件上執行“滑動”操作,一般是針對整個屏幕。這個方法不支持通過坐標來操作,并且僅僅是簡單的模擬單個手指滑動。這個方法對于諸如相冊分頁、切換視圖等情況可能會發揮比較大的作用。更復雜的場景可能需要用到`mobile:dragFromToForDuration`,這個方法支持傳坐標(coordinates )和滑動持續時間(duration)。
#### 支持參數
* _direction_: 'up', 'down', 'left' or 'right'. 這4個參數是固定的。
* _element_: 需要滑動的控件ID(作為十六進制哈希字符串)。如果沒有提供該參數的話,則會使用App的控件作為替代。
#### 用法示例
```java
// Java
JavascriptExecutor js = (JavascriptExecutor) driver;
Map<String, Object> params = new HashMap<>();
scrollObject.put("direction", "down");
scrollObject.put("element", ((RemoteWebElement) element).getId());
js.executeScript("mobile: swipe", params);
```
### mobile: scroll
滾動元素或整個屏幕。支持不同的滾動策略。該方法提供了4個可選擇滑動策略:按照順序有“name”,“direction”,“predicateString”或“toVisible”。所有的滑動策略都是排他性的,一次滑動只能選擇一個策略。你可以使用`mobile:scroll`來對表格中或者集合視圖中的某個已知控件進行精確的滾動操作。然而目前有一個已知的局限問題:如果需要在父容器上執行太多的滾動手勢到達指定的某個子元素(幾十個子元素),則方法調用可能會失敗。
#### 支持參數
* _element_: 需要滾動的控件ID(作為十六進制哈希字符串)。如果沒有提供該參數的話,則會使用App的控件作為替代。
* _name_: 需要執行滾動的子控件的`accessibility id`。
將`predicateString`參數設置為`“name == accessibilityId”`可以實現相同的結果。如果`element`不是容器,則不起作用。
* _direction_: 'up', 'down', 'left' or 'right'. 該參數與`swipe`中的比,差別在于`scroll`會嘗試將當前界面完全移動到下一頁。(`page`一詞表示單個設備屏幕中的所有內容)
* _predicateString_: 需要被執行滾動操作的子控件的NSPredicate定位器。如果控件不是容器,則不起作用。
* _toVisible_: 布爾類型的參數。如果設置為`true`,則表示要求滾動到父控件中的第一個可見到的子控件。如果`element`未設置,則不生效。
#### 用法示例
```python
# Python
driver.execute_script('mobile: scroll', {'direction': 'down'});
```
### mobile: pinch
在給定的控件或應用程序控件上執行捏合手勢。
#### 支持參數
* _element_: 需要捏合的控件ID(作為十六進制哈希字符串)。如果沒有提供該參數的話,則會使用App的控件作為替代。
* _scale_: 浮動型夾點尺度。使用0和1之間的比例來“捏緊”或縮小,大于1的比例“撐開”或放大。強制參數
* _velocity_: 每秒縮放速度(浮點值)。強制參數
#### 用法示例
```ruby
# Ruby
execute_script 'mobile: pinch', scale: 0.5, velocity: 1.1, element: element.ref
```
### mobile: doubleTap
在指定控件上或屏幕上執行雙擊手勢。
#### 支持參數
* _element_: 需要雙擊的控件ID(作為十六進制哈希字符串)。如果沒有提供該參數的話,則會使用App的控件作為替代。
* _x_: 屏幕x軸坐標點,浮點型. 僅當`element`未設置時才是強制參數
* _y_: 屏幕y軸坐標點,浮點型. 僅當`element`未設置時才是強制參數
#### 用法示例
```javascript
// javascript
driver.execute('mobile: doubleTap', {element: element.value.ELEMENT});
```
### mobile: touchAndHold
在指定控件或屏幕上長按的手勢操作。
#### 支持參數
* _element_: 需要長按的控件ID(作為十六進制哈希字符串)。如果沒有提供該參數的話,則會使用App的控件作為替代。
* _duration_: 長按的持續時間(秒),浮點型。強制性參數
* _x_: 屏幕x軸坐標點,浮點型. 僅當`element`未設置時才是強制參數
* _y_: 屏幕y軸坐標點,浮點型. 僅當`element`未設置時才是強制參數
#### 用法示例
```csharp
// c#
Dictionary<string, object> tfLongTap = new Dictionary<string, object>();
tfLongTap.Add("element", element.Id);
tfLongTap.Add("duration", 2.0);
((IJavaScriptExecutor)driver).ExecuteScript("mobile: touchAndHold", tfLongTap);
```
### mobile: twoFingerTap
在給定元素或應用程序元素上執行兩個手指點擊手勢。
#### 支持參數
* _element_: 需要兩只手指操作的控件ID(作為十六進制哈希字符串)。如果沒有提供該參數的話,則會使用App的控件作為替代。
#### 用法示例
```csharp
// c#
Dictionary<string, object> tfTap = new Dictionary<string, object>();
tfTap.Add("element", element.Id);
((IJavaScriptExecutor)driver).ExecuteScript("mobile: twoFingerTap", tfTap);
```
### mobile: tap
在指定控件或屏幕上的坐標執行點擊手勢。
#### 支持參數
* _element_: 控件ID(作為十六進制哈希字符串)。 如果設置 了`element`參數,則`x`、`y`代表的是以當前`element`為邊界的xy軸。若未設置,則`x`,`y`代表的是以手機屏幕為邊界。
* _x_: x軸坐標,類型為float。強制參數
* _y_: y軸坐標,類型為float。強制參數
#### 案例
```php
// PHP
$params = array(array('x' => 100.0, 'y' => 50.0, 'element' => element.GetAttribute("id")));
$driver->executeScript("mobile: tap", $params);
```
### mobile: dragFromToForDuration
通過坐標點執行拖放手勢。可以在控件上執行,也可以在屏幕上執行。
#### Supported arguments
* _element_: 控件ID(作為十六進制哈希字符串)。 如果設置 了`element`參數,則`x`、`y`代表的是以當前`element`為邊界的xy軸。若未設置,則`x`,`y`代表的是以手機屏幕為邊界。
* _duration_: 浮點數范圍[0.5,60]。表示開始拖動點之前的點擊手勢需要多長時間才能開始拖動。強制參數
* _fromX_: 起始拖動點的x坐標(類型float)。強制參數
* _fromY_: 起始拖動點的y坐標(類型float)。強制參數
* _toX_: 結束拖曳點的x坐標(float類型)。強制參數
* _toY_: 結束拖動點的y坐標(類型float)。強制參數
#### 用法示例
```java
// Java
JavascriptExecutor js = (JavascriptExecutor) driver;
Map<String, Object> params = new HashMap<>();
params.put("duration", 1.0);
params.put("fromX", 100);
params.put("fromY", 100);
params.put("toX", 200);
params.put("toY", 200);
params.put("element", ((RemoteWebElement) element).getId());
js.executeScript("mobile: dragFromToForDuration", params);
```
### mobile: selectPickerWheelValue
選擇下一個或上一個picker wheel的值。 如果這些值是動態的,那么這個方法是能起作用的。XCTest有一個BUG,就是你并不能知道要選擇哪一個,或者當前的選擇區域是否生效。
#### 支持參數
* _element_: PickerWheel的內部元素id(作為十六進制哈希字符串)執行值選擇。元素必須是XCUIElementTypePickerWheel類型。強制參數
* _order_: `next` 選擇下一個value,`previous`選擇前面一個value。強制參數
* _offset_: 區間值: [0.01, 0.5]。它定義了picker wheel的中心距離應該有多遠。 通過將該值乘以實際的picker wheel高度來確定實際距離。太小的偏移值可能不會改變picker wheel的值,而過高的值可能會導致picker wheel同時切換兩個或多個值。通常最優值位于范圍[0.15,0.3]中。默認為0.2
#### 用法示例
```java
// Java
JavascriptExecutor js = (JavascriptExecutor) driver;
Map<String, Object> params = new HashMap<>();
params.put("order", "next");
params.put("offset", 0.15);
params.put("element", ((RemoteWebElement) element).getId());
js.executeScript("mobile: selectPickerWheelValue", params);
```
### mobile: alert
對NSAlert實例執行操作。
#### 支持參數
* _action_: 支持以下操作: `accept`, `dismiss` and `getButtons`。強制參數
* _buttonLabel_: 點擊已有警報按鈕的標簽文本。這是一個可選參數,只能與`accept`和`dismiss` 操作相結合才有效。
#### 用法示例
```python
# Python
driver.execute_script('mobile: alert', {'action': 'accept', 'buttonLabel': 'My Cool Alert Button'});
```
### mobile: tapWithNumberOfTaps
從Appium 1.17.1.開始,對單個或者多個接觸點,點擊一次或者多次。
#### 支持參數
* _element_: 要執行一次或多次點擊的內部元素標識符(用十六進制字符串表示)
* _numberOfTaps_: 點擊次數
* _numberOfTouches_: 接觸點數量
#### 用法示例
```ruby
# Ruby
e = @driver.find_element :id, 'target element'
# Taps the element with a single touch point twice
@driver.execute_script 'mobile: tapWithNumberOfTaps', {element: e.ref, numberOfTaps: 2, numberOfTouches: 1}
```
#### 參考
[tapWithNumberOfTaps:numberOfTouches:](https://developer.apple.com/documentation/xctest/xcuielement/1618671-tapwithnumberoftaps)
### 進階主題
查看 [WDA Element Commands API](https://github.com/facebook/WebDriverAgent/blob/master/WebDriverAgentLib/Commands/FBElementCommands.m)
以獲取有關在Facebook WebDriverAgent中實現的手勢的信息。
XCTest文檔列出了關于[XCUIElement](https://developer.apple.com/documentation/xctest/xcuielement)和[XCUICoordinate](https://developer.apple.com/documentation/xctest/xcuicoordinate)方法所有可用手勢的信息。
本文由 [大東](https://testerhome.com/Anikikun) 翻譯,由 [lihuazhang](https://github.com/lihuazhang) 校驗。
- 關于TesterHome和MTSC
- 關于Appium
- 簡介
- Appium 客戶端
- 入門指南
- 已支持的平臺
- API 文檔
- Appium驅動
- XCUITest (iOS)
- XCUITest Real Devices (iOS)
- UIAutomation (iOS)
- UIAutomation Safari Launcher (iOS)
- UIAutomator (Android)
- UIAutomator2 (Android)
- Espresso (Android)
- Windows
- Mac
- Appium命令
- Status
- Execute Mobile Command
- Session
- Create
- End
- Get Session Capabilities
- Go Back
- Screenshot
- Source
- Timeouts
- Timeouts
- Implicit Wait
- Async Script
- Orientation
- Get Orientation
- Set Orientation
- Geolocation
- Get Geolocation
- Set Geolocation
- Logs
- Get Log Types
- Get Logs
- Events
- Log event
- Get events
- Settings
- Update Settings
- Get Device Settings
- Settings
- Update Settings
- Get Device Settings
- Execute Driver Script
- Device
- Activity
- Start Activity
- Current Activity
- Current Package
- App
- Install App
- Is App Installed
- Launch App
- Background App
- Close App
- Reset App
- Remove App
- Activate App
- Terminate App
- Get App State
- Get App Strings
- End Test Coverage
- Clipboard
- Get Clipboard
- Set Clipboard
- Emulator
- Power AC
- Power Capacity
- Files
- Push File
- Pull File
- Pull Folder
- Interactions
- Shake
- Lock
- Unlock
- Is Locked
- Rotate
- Keys
- Press keycode
- Long press keycode
- Hide Keyboard
- Is Keyboard Shown
- Network
- Toggle Airplane Mode
- Toggle Data
- Toggle WiFi
- Toggle Location Services
- Send SMS
- GSM Call
- GSM Signal
- GSM Voice
- Network Speed
- Performance Data
- Get Performance Data
- Performance Data Types
- Screen Recording
- Start Screen Recording
- Stop Screen Recording
- Simulator
- Perform Touch ID
- Toggle Touch ID Enrollment
- System
- Open Notifications
- System Bars
- System Time
- Display density
- Authentication
- Finger Print
- Element
- Find Element
- Find Elements
- Actions
- Click
- Send Keys
- Clear
- Attributes
- Text
- Name
- Attribute
- Selected
- Enabled
- Displayed
- Location
- Size
- Rect
- CSS Property
- Location in View
- Other
- Submit
- Active Element
- Equals Element
- Context
- Get Context
- Get All Contexts
- Set Context
- Interactions
- Mouse
- Move To
- Click
- Double Click
- Button Down
- Button Up
- Touch
- Single Tap
- Double Tap
- Move
- Touch Down
- Touch Up
- Long Press
- Scroll
- Flick
- Multi Touch Perform
- Touch Perform
- W3C Actions
- Web
- Window
- Set Window
- Close Window
- Get Handle
- Get Handles
- Get Title
- Get Window Size
- Set Window Size
- Get Window Position
- Set Window Position
- Maximize Window
- Navigation
- Go to URL
- Get URL
- Back
- Forward
- Refresh
- Storage
- Get All Cookies
- Set Cookie
- Delete Cookie
- Delete All Cookies
- Frame
- Switch to Frame
- Switch to Parent Frame
- Execute Async
- Execute
- 編寫 & 運行Appium腳本
- Running Tests
- Desired Capabilities
- The --default-capabilities flag
- Finding Elements
- Touch Actions
- CLI Arguments
- Server Security
- Web/Web Views
- Mobile Web Testing
- Automating Hybrid Apps
- Using ios-webkit-debug-proxy
- Using Chromedriver
- Image Comparison
- iOS
- Low-Level Insights on iOS Input Events
- XCUITest Mobile Gestures
- XCUITest Mobile App Management
- iOS Pasteboard Guide
- iOS Predicate Guide
- iOS Touch ID Guide
- iOS Install Certificate
- tvOS support
- Pushing/Pulling files
- Audio Capture
- Android
- Low-Level Insights on Android Input Events
- UiSelector Guide
- Espresso Datamatcher Guide
- Android Code Coverage Guide
- Activities Startup Troubleshooting Guide
- How To Execute Shell Commands On The Remote Device
- Android Device Screen Streaming
- How To Emulate IME Actions Generation
- How To Test Android App Bundle
- Other
- Reset Strategies
- Network Connection Guide
- Using Unicode with Appium
- Troubleshooting
- Tutorial
- Swipe Tutorial
- Screen
- Element
- Partial screen
- Simple
- Multiple scroll views
- Add scroll layout
- Tricks and Tips
- Screen
- Element
- Element search
- Fast
- Slow
- Guide
- 進階概念
- 定位圖像中的元素
- 使用定位元素的插件
- 遷移到 XCUITest
- 在 Appium 中使用 Selenium Grid
- Appium Logs Filtering
- 跨域 iframes
- 使用自定義 WDA 服務器
- 使用不同版本的 Xcode 運行
- The Event Timings API
- 并行測試的設置
- The Settings API
- Memory Collection
- 向Appium項目做貢獻
- 從源代碼運行 Appium
- 開發者概述
- 標準開發命令
- Appium 風格指南
- 如何編寫文檔
- Appium 包結構
- 鳴謝