From 6864eede811a64c7852d013d5ed72a8c1994c7de Mon Sep 17 00:00:00 2001 From: jayandran Date: Tue, 21 Jul 2020 13:10:59 +0530 Subject: [PATCH 1/4] Client support for Appium : Chrome Dev Protocol --- .../io/appium/java_client/AppiumDriver.java | 2 +- .../appium/java_client/ExecuteCDPCommand.java | 64 +++++++++++++ .../io/appium/java_client/MobileCommand.java | 3 + .../appium/ExecuteCDPCommandTest.java | 96 +++++++++++++++++++ 4 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 src/main/java/io/appium/java_client/ExecuteCDPCommand.java create mode 100644 src/test/java/io/appium/java_client/appium/ExecuteCDPCommandTest.java diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 32785d1eb..fd46f52ec 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -69,7 +69,7 @@ @SuppressWarnings("unchecked") public class AppiumDriver extends DefaultGenericMobileDriver implements ComparesImages, FindsByImage, FindsByCustom, - ExecutesDriverScript, LogsEvents, HasSettings { + ExecutesDriverScript, LogsEvents, HasSettings,ExecuteCDPCommand { private static final ErrorHandler errorHandler = new ErrorHandler(new ErrorCodesMobile(), true); // frequently used command parameters diff --git a/src/main/java/io/appium/java_client/ExecuteCDPCommand.java b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java new file mode 100644 index 000000000..938ec440a --- /dev/null +++ b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java @@ -0,0 +1,64 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * 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 io.appium.java_client; + +import org.openqa.selenium.remote.Response; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; +import static io.appium.java_client.MobileCommand.EXECUTE_CDP_COMMAND; + +public interface ExecuteCDPCommand extends ExecutesMethod { + + /** + * Allows to execute ChromeDevProtocol commands against Appium browser session + * + * @since Appium 1.18 + * @param command Command to execute against the browser (For Ref : https://chromedevtools.github.io/devtools-protocol/) + * @param params additional parameters required to execute the command + * @return Value (Output of the command execution) + * @throws org.openqa.selenium.WebDriverException if there was a failure while executing the command + */ + default Map executeCdpCommand(String command, @Nullable Map params) { + Map data = new HashMap<>(); + data.put("cmd",checkNotNull(command)); + if(params != null){ + data.put("params",params); + }else{ + params = new HashMap<>(); + data.put("params",params); + } + Response response = execute(EXECUTE_CDP_COMMAND, data); + Map value = (Map) response.getValue(); + return value; + } + + /** + * Allows to execute ChromeDevProtocol commands against Appium browser session without parameters + * + * @since Appium 1.18 + * @param command Command to execute against the browser (For Ref : https://chromedevtools.github.io/devtools-protocol/) + * @return Value (Output of the command execution) + * @throws org.openqa.selenium.WebDriverException if there was a failure while executing the command + */ + default Map executeCdpCommand(String command) { + return executeCdpCommand(command,null); + } +} diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 58a3b6098..664802635 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -114,6 +114,7 @@ public class MobileCommand { protected static final String COMPARE_IMAGES; protected static final String EXECUTE_DRIVER_SCRIPT; protected static final String GET_ALLSESSION; + protected static final String EXECUTE_CDP_COMMAND; public static final Map commandRepository; @@ -192,6 +193,7 @@ public class MobileCommand { COMPARE_IMAGES = "compareImages"; EXECUTE_DRIVER_SCRIPT = "executeDriverScript"; GET_ALLSESSION = "getAllSessions"; + EXECUTE_CDP_COMMAND = "executeCdp"; commandRepository = new HashMap<>(); commandRepository.put(RESET, postC("/session/:sessionId/appium/app/reset")); @@ -282,6 +284,7 @@ public class MobileCommand { commandRepository.put(COMPARE_IMAGES, postC("/session/:sessionId/appium/compare_images")); commandRepository.put(EXECUTE_DRIVER_SCRIPT, postC("/session/:sessionId/appium/execute_driver")); commandRepository.put(GET_ALLSESSION, getC("/sessions")); + commandRepository.put(EXECUTE_CDP_COMMAND, postC("/session/:sessionId/goog/cdp/execute")); } /** diff --git a/src/test/java/io/appium/java_client/appium/ExecuteCDPCommandTest.java b/src/test/java/io/appium/java_client/appium/ExecuteCDPCommandTest.java new file mode 100644 index 000000000..e878eb9c6 --- /dev/null +++ b/src/test/java/io/appium/java_client/appium/ExecuteCDPCommandTest.java @@ -0,0 +1,96 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * 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 io.appium.java_client.appium; + +import io.appium.java_client.AppiumDriver; +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; +import io.appium.java_client.remote.MobileBrowserType; +import io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.service.local.AppiumDriverLocalService; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.DesiredCapabilities; +import org.openqa.selenium.remote.RemoteWebElement; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.PageFactory; + +import java.util.HashMap; +import java.util.Map; + +import static java.time.Duration.ofSeconds; +import static org.junit.Assert.assertNotNull; + +public class ExecuteCDPCommandTest { + + private WebDriver driver; + + private AppiumDriverLocalService service; + + @FindBy(name = "q") + private WebElement searchTextField; + + + /** + * The setting up. + */ + @Before public void setUp() { + service = AppiumDriverLocalService.buildDefaultService(); + service.start(); + + DesiredCapabilities capabilities = new DesiredCapabilities(); + capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); + capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.CHROME); + capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME,"UiAutomator2"); + driver = new AndroidDriver(service.getUrl(), capabilities); + //This time out is set because test can be run on slow Android SDK emulator + PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(5)), this); + } + + /** + * finishing. + */ + @After public void tearDown() { + if (driver != null) { + driver.quit(); + } + + if (service != null) { + service.stop(); + } + } + + @Test public void testExecuteCDPCommandWithoutParam() { + driver.get("https://www.google.com"); + searchTextField.sendKeys("Hello"); + Map cookies = ((AppiumDriver)driver).executeCdpCommand("Page.getCookies"); + assertNotNull(cookies); + } + + @Test public void testExecuteCDPCommandWithParams() { + Map params = new HashMap(); + params.put("latitude", 13.0827); + params.put("longitude",80.2707); + params.put("accuracy",1); + ((AppiumDriver)driver).executeCdpCommand("Emulation.setGeolocationOverride",params); + driver.get("https://www.google.com"); + } + +} From 91b35264f6daeafa58f0fcc614bda4725a25c177 Mon Sep 17 00:00:00 2001 From: jayandran Date: Tue, 21 Jul 2020 21:13:11 +0530 Subject: [PATCH 2/4] Review Changes - Client support for Appium : Chrome Dev Protocol --- .../io/appium/java_client/AppiumDriver.java | 2 +- .../appium/java_client/ExecuteCDPCommand.java | 35 +++++++++---------- .../io/appium/java_client/MobileCommand.java | 6 ++-- .../java_client/android/AndroidDriver.java | 3 +- .../ExecuteCDPCommandTest.java | 26 ++++++++------ 5 files changed, 37 insertions(+), 35 deletions(-) rename src/test/java/io/appium/java_client/{appium => android}/ExecuteCDPCommandTest.java (82%) diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index fd46f52ec..32785d1eb 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -69,7 +69,7 @@ @SuppressWarnings("unchecked") public class AppiumDriver extends DefaultGenericMobileDriver implements ComparesImages, FindsByImage, FindsByCustom, - ExecutesDriverScript, LogsEvents, HasSettings,ExecuteCDPCommand { + ExecutesDriverScript, LogsEvents, HasSettings { private static final ErrorHandler errorHandler = new ErrorHandler(new ErrorCodesMobile(), true); // frequently used command parameters diff --git a/src/main/java/io/appium/java_client/ExecuteCDPCommand.java b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java index 938ec440a..d1d25189d 100644 --- a/src/main/java/io/appium/java_client/ExecuteCDPCommand.java +++ b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java @@ -16,49 +16,46 @@ package io.appium.java_client; +import com.google.common.collect.ImmutableMap; import org.openqa.selenium.remote.Response; import javax.annotation.Nullable; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import static com.google.common.base.Preconditions.checkNotNull; -import static io.appium.java_client.MobileCommand.EXECUTE_CDP_COMMAND; +import static io.appium.java_client.MobileCommand.EXECUTE_GOOGLE_CDP_COMMAND; public interface ExecuteCDPCommand extends ExecutesMethod { /** - * Allows to execute ChromeDevProtocol commands against Appium browser session + * Allows to execute ChromeDevProtocol commands against Android Chrome browser session * - * @since Appium 1.18 * @param command Command to execute against the browser (For Ref : https://chromedevtools.github.io/devtools-protocol/) - * @param params additional parameters required to execute the command + * @param params additional parameters required to execute the command * @return Value (Output of the command execution) * @throws org.openqa.selenium.WebDriverException if there was a failure while executing the command + * @since Appium 1.18 */ - default Map executeCdpCommand(String command, @Nullable Map params) { + default Map executeCdpCommand(String command, @Nullable Map params) { Map data = new HashMap<>(); - data.put("cmd",checkNotNull(command)); - if(params != null){ - data.put("params",params); - }else{ - params = new HashMap<>(); - data.put("params",params); - } - Response response = execute(EXECUTE_CDP_COMMAND, data); - Map value = (Map) response.getValue(); - return value; + data.put("cmd", checkNotNull(command)); + data.put("params", params == null ? Collections.emptyMap() : params); + Response response = execute(EXECUTE_GOOGLE_CDP_COMMAND, data); + //noinspection unchecked + return ImmutableMap.copyOf((Map) response.getValue()); } /** - * Allows to execute ChromeDevProtocol commands against Appium browser session without parameters + * Allows to execute ChromeDevProtocol commands against Android Chrome browser session without parameters * - * @since Appium 1.18 * @param command Command to execute against the browser (For Ref : https://chromedevtools.github.io/devtools-protocol/) * @return Value (Output of the command execution) * @throws org.openqa.selenium.WebDriverException if there was a failure while executing the command + * @since Appium 1.18 */ - default Map executeCdpCommand(String command) { - return executeCdpCommand(command,null); + default Map executeCdpCommand(String command) { + return executeCdpCommand(command, null); } } diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 664802635..df50c962f 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -114,7 +114,7 @@ public class MobileCommand { protected static final String COMPARE_IMAGES; protected static final String EXECUTE_DRIVER_SCRIPT; protected static final String GET_ALLSESSION; - protected static final String EXECUTE_CDP_COMMAND; + protected static final String EXECUTE_GOOGLE_CDP_COMMAND; public static final Map commandRepository; @@ -193,7 +193,7 @@ public class MobileCommand { COMPARE_IMAGES = "compareImages"; EXECUTE_DRIVER_SCRIPT = "executeDriverScript"; GET_ALLSESSION = "getAllSessions"; - EXECUTE_CDP_COMMAND = "executeCdp"; + EXECUTE_GOOGLE_CDP_COMMAND = "executeCdp"; commandRepository = new HashMap<>(); commandRepository.put(RESET, postC("/session/:sessionId/appium/app/reset")); @@ -284,7 +284,7 @@ public class MobileCommand { commandRepository.put(COMPARE_IMAGES, postC("/session/:sessionId/appium/compare_images")); commandRepository.put(EXECUTE_DRIVER_SCRIPT, postC("/session/:sessionId/appium/execute_driver")); commandRepository.put(GET_ALLSESSION, getC("/sessions")); - commandRepository.put(EXECUTE_CDP_COMMAND, postC("/session/:sessionId/goog/cdp/execute")); + commandRepository.put(EXECUTE_GOOGLE_CDP_COMMAND, postC("/session/:sessionId/goog/cdp/execute")); } /** diff --git a/src/main/java/io/appium/java_client/android/AndroidDriver.java b/src/main/java/io/appium/java_client/android/AndroidDriver.java index 9fc18bd51..62016e814 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -25,6 +25,7 @@ import io.appium.java_client.AppiumDriver; import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecuteCDPCommand; import io.appium.java_client.FindsByAndroidDataMatcher; import io.appium.java_client.FindsByAndroidViewMatcher; import io.appium.java_client.FindsByAndroidUIAutomator; @@ -67,7 +68,7 @@ public class AndroidDriver HasSupportedPerformanceDataType, AuthenticatesByFinger, HasOnScreenKeyboard, CanRecordScreen, SupportsSpecialEmulatorCommands, SupportsNetworkStateManagement, ListensToLogcatMessages, HasAndroidClipboard, - HasBattery { + HasBattery, ExecuteCDPCommand { private static final String ANDROID_PLATFORM = MobilePlatform.ANDROID; diff --git a/src/test/java/io/appium/java_client/appium/ExecuteCDPCommandTest.java b/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java similarity index 82% rename from src/test/java/io/appium/java_client/appium/ExecuteCDPCommandTest.java rename to src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java index e878eb9c6..ac098f3b3 100644 --- a/src/test/java/io/appium/java_client/appium/ExecuteCDPCommandTest.java +++ b/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.appium.java_client.appium; +package io.appium.java_client.android; import io.appium.java_client.AppiumDriver; import io.appium.java_client.android.AndroidDriver; @@ -51,14 +51,15 @@ public class ExecuteCDPCommandTest { /** * The setting up. */ - @Before public void setUp() { + @Before + public void setUp() { service = AppiumDriverLocalService.buildDefaultService(); service.start(); DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.CHROME); - capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME,"UiAutomator2"); + capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "UiAutomator2"); driver = new AndroidDriver(service.getUrl(), capabilities); //This time out is set because test can be run on slow Android SDK emulator PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(5)), this); @@ -67,7 +68,8 @@ public class ExecuteCDPCommandTest { /** * finishing. */ - @After public void tearDown() { + @After + public void tearDown() { if (driver != null) { driver.quit(); } @@ -77,19 +79,21 @@ public class ExecuteCDPCommandTest { } } - @Test public void testExecuteCDPCommandWithoutParam() { + @Test + public void testExecuteCDPCommandWithoutParam() { driver.get("https://www.google.com"); searchTextField.sendKeys("Hello"); - Map cookies = ((AppiumDriver)driver).executeCdpCommand("Page.getCookies"); + Map cookies = ((AndroidDriver) driver).executeCdpCommand("Page.getCookies"); assertNotNull(cookies); } - @Test public void testExecuteCDPCommandWithParams() { - Map params = new HashMap(); + @Test + public void testExecuteCDPCommandWithParams() { + Map params = new HashMap(); params.put("latitude", 13.0827); - params.put("longitude",80.2707); - params.put("accuracy",1); - ((AppiumDriver)driver).executeCdpCommand("Emulation.setGeolocationOverride",params); + params.put("longitude", 80.2707); + params.put("accuracy", 1); + ((AndroidDriver) driver).executeCdpCommand("Emulation.setGeolocationOverride", params); driver.get("https://www.google.com"); } From 6c7258c81fccdde93282278e30835cc8f95e341a Mon Sep 17 00:00:00 2001 From: jayandran Date: Thu, 23 Jul 2020 19:29:02 +0530 Subject: [PATCH 3/4] Review changes for documentation --- src/main/java/io/appium/java_client/ExecuteCDPCommand.java | 2 +- .../io/appium/java_client/android/ExecuteCDPCommandTest.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/io/appium/java_client/ExecuteCDPCommand.java b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java index d1d25189d..eb01141d9 100644 --- a/src/main/java/io/appium/java_client/ExecuteCDPCommand.java +++ b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java @@ -33,7 +33,7 @@ public interface ExecuteCDPCommand extends ExecutesMethod { * Allows to execute ChromeDevProtocol commands against Android Chrome browser session * * @param command Command to execute against the browser (For Ref : https://chromedevtools.github.io/devtools-protocol/) - * @param params additional parameters required to execute the command + * @param params additional parameters required to execute the command * @return Value (Output of the command execution) * @throws org.openqa.selenium.WebDriverException if there was a failure while executing the command * @since Appium 1.18 diff --git a/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java b/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java index ac098f3b3..3637d0360 100644 --- a/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java +++ b/src/test/java/io/appium/java_client/android/ExecuteCDPCommandTest.java @@ -16,8 +16,6 @@ package io.appium.java_client.android; -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.pagefactory.AppiumFieldDecorator; import io.appium.java_client.remote.MobileBrowserType; import io.appium.java_client.remote.MobileCapabilityType; From 4fe55ea1780ca3f41a3a35a45a83cd02e42d3e73 Mon Sep 17 00:00:00 2001 From: jayandran Date: Thu, 23 Jul 2020 20:23:30 +0530 Subject: [PATCH 4/4] CheckStyle Fix --- src/main/java/io/appium/java_client/ExecuteCDPCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/appium/java_client/ExecuteCDPCommand.java b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java index eb01141d9..8cf09f357 100644 --- a/src/main/java/io/appium/java_client/ExecuteCDPCommand.java +++ b/src/main/java/io/appium/java_client/ExecuteCDPCommand.java @@ -30,7 +30,7 @@ public interface ExecuteCDPCommand extends ExecutesMethod { /** - * Allows to execute ChromeDevProtocol commands against Android Chrome browser session + * Allows to execute ChromeDevProtocol commands against Android Chrome browser session. * * @param command Command to execute against the browser (For Ref : https://chromedevtools.github.io/devtools-protocol/) * @param params additional parameters required to execute the command @@ -48,7 +48,7 @@ default Map executeCdpCommand(String command, @Nullable Map