diff --git a/README.md b/README.md
index 2cbecb5..8c0f686 100644
--- a/README.md
+++ b/README.md
@@ -58,14 +58,14 @@ sonic-driver-core can be separated from appium and interact directly with webdri
io.github.soniccloudorg
sonic-driver-core
- 1.0.5
+ 1.0.6
```
#### Gradle
```
-implementation 'io.github.soniccloudorg:sonic-driver-core:1.0.5'
+implementation 'io.github.soniccloudorg:sonic-driver-core:1.0.6'
```
### Code
diff --git a/README_CN.md b/README_CN.md
index 7ab1d99..2a238d9 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -53,12 +53,12 @@ sonic-driver-core可以脱离Appium,直接与WebDriverAgent或UIautomator2交
io.github.soniccloudorg
sonic-driver-core
- 1.0.5
+ 1.0.6
```
#### Gradle
```
-implementation 'io.github.soniccloudorg:sonic-driver-core:1.0.5'
+implementation 'io.github.soniccloudorg:sonic-driver-core:1.0.6'
```
### 代码
diff --git a/pom.xml b/pom.xml
index a3fc125..11170a3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
io.github.soniccloudorg
sonic-driver-core
- 1.0.5
+ 1.0.6
sonic-driver-core
The Sonic Project UIAutomation Driver Core for Android, iOS, Windows, Mac and so on.
diff --git a/src/main/java/org/cloud/sonic/core/ios/IOSDriver.java b/src/main/java/org/cloud/sonic/core/ios/IOSDriver.java
index b799a3b..0acba52 100644
--- a/src/main/java/org/cloud/sonic/core/ios/IOSDriver.java
+++ b/src/main/java/org/cloud/sonic/core/ios/IOSDriver.java
@@ -24,6 +24,8 @@
import org.cloud.sonic.core.ios.service.impl.WdaClientImpl;
import org.cloud.sonic.core.tool.SonicRespException;
+import java.util.List;
+
/**
* @author Eason
* ios driver
@@ -459,4 +461,118 @@ public WebElement findElement(XCUIElementType xcuiElementType, Integer retry, In
public WebElement findElement(String selector, String value, Integer retry, Integer interval) throws SonicRespException {
return wdaClient.findElement(selector, value, retry, interval);
}
+
+ /**
+ * find element list in device.
+ *
+ * @param iosSelector
+ * @param value
+ * @return
+ * @throws SonicRespException
+ */
+ public List findElementList(IOSSelector iosSelector, String value) throws SonicRespException {
+ return findElementList(iosSelector, value, null);
+ }
+
+ /**
+ * find element list in device.
+ *
+ * @param xcuiElementType
+ * @return
+ * @throws SonicRespException
+ */
+ public List findElementList(XCUIElementType xcuiElementType) throws SonicRespException {
+ return findElementList(xcuiElementType, null);
+ }
+
+ /**
+ * find element list in device.
+ *
+ * @param selector
+ * @param value
+ * @return
+ * @throws SonicRespException
+ */
+ public List findElementList(String selector, String value) throws SonicRespException {
+ return findElementList(selector, value, null);
+ }
+
+ /**
+ * find element list in device.
+ *
+ * @param iosSelector
+ * @param value
+ * @param retry
+ * @return
+ * @throws SonicRespException
+ */
+ public List findElementList(IOSSelector iosSelector, String value, Integer retry) throws SonicRespException {
+ return findElementList(iosSelector, value, retry, null);
+ }
+
+ /**
+ * find element list in device.
+ *
+ * @param xcuiElementType
+ * @param retry
+ * @return
+ * @throws SonicRespException
+ */
+ public List findElementList(XCUIElementType xcuiElementType, Integer retry) throws SonicRespException {
+ return findElementList(xcuiElementType, retry, null);
+ }
+
+ /**
+ * find element list in device.
+ *
+ * @param selector
+ * @param value
+ * @param retry
+ * @return
+ * @throws SonicRespException
+ */
+ public List findElementList(String selector, String value, Integer retry) throws SonicRespException {
+ return findElementList(selector, value, retry, null);
+ }
+
+ /**
+ * find element list in device.
+ *
+ * @param iosSelector
+ * @param value
+ * @param retry
+ * @param interval
+ * @return
+ * @throws SonicRespException
+ */
+ public List findElementList(IOSSelector iosSelector, String value, Integer retry, Integer interval) throws SonicRespException {
+ return findElementList(iosSelector.getSelector(), value, retry, interval);
+ }
+
+ /**
+ * find element list in device.
+ *
+ * @param xcuiElementType
+ * @param retry
+ * @param interval
+ * @return
+ * @throws SonicRespException
+ */
+ public List findElementList(XCUIElementType xcuiElementType, Integer retry, Integer interval) throws SonicRespException {
+ return findElementList(IOSSelector.CLASS_NAME.getSelector(), xcuiElementType.getType(), retry, interval);
+ }
+
+ /**
+ * find element list in device.
+ *
+ * @param selector
+ * @param value
+ * @param retry
+ * @param interval
+ * @return
+ * @throws SonicRespException
+ */
+ public List findElementList(String selector, String value, Integer retry, Integer interval) throws SonicRespException {
+ return wdaClient.findElementList(selector, value, retry, interval);
+ }
}
diff --git a/src/main/java/org/cloud/sonic/core/ios/models/IOSRect.java b/src/main/java/org/cloud/sonic/core/ios/models/IOSRect.java
new file mode 100644
index 0000000..a0999e3
--- /dev/null
+++ b/src/main/java/org/cloud/sonic/core/ios/models/IOSRect.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) [SonicCloudOrg] Sonic Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.cloud.sonic.core.ios.models;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.ToString;
+
+@Getter
+@ToString
+@AllArgsConstructor
+public class IOSRect {
+ private int x;
+ private int y;
+ private int width;
+ private int height;
+}
diff --git a/src/main/java/org/cloud/sonic/core/ios/models/SessionInfo.java b/src/main/java/org/cloud/sonic/core/ios/models/SessionInfo.java
index 5899430..ce8d1c6 100644
--- a/src/main/java/org/cloud/sonic/core/ios/models/SessionInfo.java
+++ b/src/main/java/org/cloud/sonic/core/ios/models/SessionInfo.java
@@ -18,8 +18,10 @@
import lombok.AllArgsConstructor;
import lombok.Getter;
+import lombok.ToString;
@Getter
+@ToString
@AllArgsConstructor
public class SessionInfo {
private String sessionId;
diff --git a/src/main/java/org/cloud/sonic/core/ios/service/WdaClient.java b/src/main/java/org/cloud/sonic/core/ios/service/WdaClient.java
index f6203cc..3e6995e 100644
--- a/src/main/java/org/cloud/sonic/core/ios/service/WdaClient.java
+++ b/src/main/java/org/cloud/sonic/core/ios/service/WdaClient.java
@@ -21,6 +21,8 @@
import org.cloud.sonic.core.ios.models.TouchActions;
import org.cloud.sonic.core.tool.SonicRespException;
+import java.util.List;
+
/**
* @author Eason
* wda client interface
@@ -83,4 +85,7 @@ public interface WdaClient {
//element handler.
WebElement findElement(String selector, String value, Integer retry, Integer interval) throws SonicRespException;
+
+ //element handler.
+ List findElementList(String selector, String value, Integer retry, Integer interval) throws SonicRespException;
}
diff --git a/src/main/java/org/cloud/sonic/core/ios/service/WebElement.java b/src/main/java/org/cloud/sonic/core/ios/service/WebElement.java
index b4d186a..a87482e 100644
--- a/src/main/java/org/cloud/sonic/core/ios/service/WebElement.java
+++ b/src/main/java/org/cloud/sonic/core/ios/service/WebElement.java
@@ -16,6 +16,7 @@
*/
package org.cloud.sonic.core.ios.service;
+import org.cloud.sonic.core.ios.models.IOSRect;
import org.cloud.sonic.core.tool.SonicRespException;
/**
@@ -29,4 +30,10 @@ public interface WebElement {
void sendKeys(String text) throws SonicRespException;
void sendKeys(String text,int frequency) throws SonicRespException;
+
+ void clear() throws SonicRespException;
+
+ String getText() throws SonicRespException;
+
+ IOSRect getRect() throws SonicRespException;
}
diff --git a/src/main/java/org/cloud/sonic/core/ios/service/impl/WdaClientImpl.java b/src/main/java/org/cloud/sonic/core/ios/service/impl/WdaClientImpl.java
index de56416..a4bbb56 100644
--- a/src/main/java/org/cloud/sonic/core/ios/service/impl/WdaClientImpl.java
+++ b/src/main/java/org/cloud/sonic/core/ios/service/impl/WdaClientImpl.java
@@ -30,6 +30,7 @@
import org.cloud.sonic.core.tool.SonicRespException;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
@@ -371,4 +372,50 @@ public WebElement findElement(String selector, String value, Integer retry, Inte
}
return webElement;
}
+
+ @Override
+ public List findElementList(String selector, String value, Integer retry, Integer interval) throws SonicRespException {
+ List webElementList = new ArrayList<>();
+ int wait = 0;
+ int intervalInit = (interval == null ? FIND_ELEMENT_INTERVAL : interval);
+ int retryInit = (retry == null ? FIND_ELEMENT_RETRY : retry);
+ String errMsg = "";
+ while (wait < retryInit) {
+ wait++;
+ checkSessionId();
+ JSONObject data = new JSONObject();
+ data.put("using", selector);
+ data.put("value", value);
+ BaseResp b = respHandler.getResp(HttpUtil.createPost(remoteUrl + "/session/" + sessionId + "/elements")
+ .body(data.toJSONString()));
+ if (b.getErr() == null) {
+ log.info("find elements successful.");
+ List ids = JSON.parseObject(b.getValue().toString(), ArrayList.class);
+ for (JSONObject ele : ids) {
+ String id = parseElementId(ele);
+ if (id.length() > 0) {
+ webElementList.add(new WebElementImpl(id, this));
+ } else {
+ log.error("parse element id {} failed.", ele);
+ continue;
+ }
+ }
+ break;
+ } else {
+ log.error("elements not found. retried {} times, retry in {} ms.", wait, intervalInit);
+ errMsg = b.getErr().getMessage();
+ }
+ if (wait < retryInit) {
+ try {
+ Thread.sleep(intervalInit);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ if (webElementList.size() == 0) {
+ throw new SonicRespException(errMsg);
+ }
+ return webElementList;
+ }
}
diff --git a/src/main/java/org/cloud/sonic/core/ios/service/impl/WebElementImpl.java b/src/main/java/org/cloud/sonic/core/ios/service/impl/WebElementImpl.java
index a56d511..cd55a1c 100644
--- a/src/main/java/org/cloud/sonic/core/ios/service/impl/WebElementImpl.java
+++ b/src/main/java/org/cloud/sonic/core/ios/service/impl/WebElementImpl.java
@@ -18,8 +18,10 @@
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.cloud.sonic.core.ios.models.BaseResp;
+import org.cloud.sonic.core.ios.models.IOSRect;
import org.cloud.sonic.core.ios.service.WdaClient;
import org.cloud.sonic.core.ios.service.WebElement;
import org.cloud.sonic.core.tool.SonicRespException;
@@ -61,7 +63,8 @@ public void sendKeys(String text, int frequency) throws SonicRespException {
data.put("frequency", frequency);
BaseResp b = wdaClient.getRespHandler().getResp(
HttpUtil.createPost(wdaClient.getRemoteUrl() + "/session/"
- + wdaClient.getSessionId() + "/element/" + id + "/value"));
+ + wdaClient.getSessionId() + "/element/" + id + "/value")
+ .body(data.toJSONString()), 60000);
if (b.getErr() == null) {
log.info("send key to {}.", id);
} else {
@@ -69,4 +72,49 @@ public void sendKeys(String text, int frequency) throws SonicRespException {
throw new SonicRespException(b.getErr().getMessage());
}
}
+
+ @Override
+ public void clear() throws SonicRespException {
+ wdaClient.checkSessionId();
+ BaseResp b = wdaClient.getRespHandler().getResp(
+ HttpUtil.createPost(wdaClient.getRemoteUrl() + "/session/"
+ + wdaClient.getSessionId() + "/element/" + id + "/clear"), 60000);
+ if (b.getErr() == null) {
+ log.info("clear {}.", id);
+ } else {
+ log.error("clear {} failed.", id);
+ throw new SonicRespException(b.getErr().getMessage());
+ }
+ }
+
+ @Override
+ public String getText() throws SonicRespException {
+ wdaClient.checkSessionId();
+ BaseResp b = wdaClient.getRespHandler().getResp(
+ HttpUtil.createGet(wdaClient.getRemoteUrl() + "/session/"
+ + wdaClient.getSessionId() + "/element/" + id + "/text"));
+ if (b.getErr() == null) {
+ log.info("get {} text {}.", id, b.getValue());
+ return b.getValue().toString();
+ } else {
+ log.error("get {} text failed.", id);
+ throw new SonicRespException(b.getErr().getMessage());
+ }
+ }
+
+ @Override
+ public IOSRect getRect() throws SonicRespException {
+ wdaClient.checkSessionId();
+ BaseResp b = wdaClient.getRespHandler().getResp(
+ HttpUtil.createGet(wdaClient.getRemoteUrl() + "/session/"
+ + wdaClient.getSessionId() + "/element/" + id + "/rect"));
+ if (b.getErr() == null) {
+ log.info("get {} rect {}.", id, b.getValue());
+ IOSRect iosRect = JSON.parseObject(b.getValue().toString(),IOSRect.class);
+ return iosRect;
+ } else {
+ log.error("get {} rect failed.", id);
+ throw new SonicRespException(b.getErr().getMessage());
+ }
+ }
}
diff --git a/src/test/java/org/cloud/sonic/core/ios/IOSDriverTest.java b/src/test/java/org/cloud/sonic/core/ios/IOSDriverTest.java
index 3fd24a6..0f5e25c 100644
--- a/src/test/java/org/cloud/sonic/core/ios/IOSDriverTest.java
+++ b/src/test/java/org/cloud/sonic/core/ios/IOSDriverTest.java
@@ -19,6 +19,7 @@
import com.alibaba.fastjson.JSONObject;
import org.cloud.sonic.core.ios.enums.*;
import org.cloud.sonic.core.ios.models.*;
+import org.cloud.sonic.core.ios.service.WebElement;
import org.cloud.sonic.core.tool.SonicRespException;
import org.junit.*;
import org.junit.runner.RunWith;
@@ -124,7 +125,7 @@ public void testPasteboard() throws SonicRespException, InterruptedException {
iosDriver.findElement(IOSSelector.ACCESSIBILITY_ID, "WebDriverAgentRunner-Runner").click();
iosDriver.setPasteboard(PasteboardType.PLAIN_TEXT, text);
Thread.sleep(1000);
- Assert.assertEquals(text, new String(iosDriver.getPasteboard(PasteboardType.PLAIN_TEXT.getType())));
+ Assert.assertEquals(text, new String(iosDriver.getPasteboard(PasteboardType.PLAIN_TEXT)));
iosDriver.pressButton(SystemButton.HOME);
}
@@ -206,14 +207,37 @@ public void testSession() {
}
@Test
- public void testFindElement() throws SonicRespException {
+ public void testFindElement() throws SonicRespException, InterruptedException {
iosDriver.pressButton(SystemButton.HOME);
+ Thread.sleep(2000);
iosDriver.findElement("accessibility id", "地图").click();
+ iosDriver.findElement(XCUIElementType.ANY);
+ Thread.sleep(2000);
iosDriver.pressButton(SystemButton.HOME);
+ Thread.sleep(2000);
iosDriver.findElement(IOSSelector.ACCESSIBILITY_ID, "地图").click();
+ Thread.sleep(2000);
+ iosDriver.findElement(IOSSelector.ACCESSIBILITY_ID, "搜索地点或地址").click();
+ WebElement w = iosDriver.findElement(IOSSelector.ACCESSIBILITY_ID, "搜索地点或地址");
+ String text = UUID.randomUUID().toString();
+ w.sendKeys(text);
+ Assert.assertEquals(text, w.getText());
+ w.clear();
+ Assert.assertEquals("搜索地点或地址", w.getText());
+ IOSRect iosRect = w.getRect();
+ Assert.assertTrue(iosRect.getX() > 0);
+ Assert.assertTrue(iosRect.getY() > 0);
+ Assert.assertTrue(iosRect.getWidth() > 0);
+ Assert.assertTrue(iosRect.getHeight() > 0);
+ iosDriver.findElement(IOSSelector.ACCESSIBILITY_ID, "取消").click();
iosDriver.pressButton(SystemButton.HOME);
- iosDriver.findElement(XCUIElementType.ANY);
- iosDriver.pressButton(SystemButton.HOME);
+ }
+
+ @Test
+ public void testFindElementList() throws SonicRespException {
+ int eleSize = iosDriver.findElementList(XCUIElementType.WINDOW).size();
+ Assert.assertEquals(eleSize,iosDriver.findElementList("class name","XCUIElementTypeWindow").size());
+ Assert.assertEquals(eleSize,iosDriver.findElementList(IOSSelector.CLASS_NAME,"XCUIElementTypeWindow").size());
}
@AfterClass