diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index b41879151..58ff20702 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -19,25 +19,11 @@ import static com.google.common.base.Preconditions.checkNotNull; -import static io.appium.java_client.MobileCommand.CLOSE_APP; -import static io.appium.java_client.MobileCommand.GET_DEVICE_TIME; import static io.appium.java_client.MobileCommand.GET_SESSION; import static io.appium.java_client.MobileCommand.GET_SETTINGS; -import static io.appium.java_client.MobileCommand.GET_STRINGS; -import static io.appium.java_client.MobileCommand.HIDE_KEYBOARD; -import static io.appium.java_client.MobileCommand.INSTALL_APP; -import static io.appium.java_client.MobileCommand.IS_APP_INSTALLED; -import static io.appium.java_client.MobileCommand.LAUNCH_APP; -import static io.appium.java_client.MobileCommand.PERFORM_MULTI_TOUCH; -import static io.appium.java_client.MobileCommand.PERFORM_TOUCH_ACTION; -import static io.appium.java_client.MobileCommand.PULL_FILE; -import static io.appium.java_client.MobileCommand.PULL_FOLDER; -import static io.appium.java_client.MobileCommand.REMOVE_APP; -import static io.appium.java_client.MobileCommand.RUN_APP_IN_BACKGROUND; import static io.appium.java_client.MobileCommand.SET_SETTINGS; import static io.appium.java_client.MobileCommand.prepareArguments; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -75,7 +61,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import javax.xml.bind.DatatypeConverter; /** * @param the required type of class which implement {@link org.openqa.selenium.WebElement}. @@ -231,123 +216,10 @@ public List findElementsByXPath(String using) { return super.findElementsByAccessibilityId(using); } - @Override protected Response execute(String command) { - return super.execute(command, ImmutableMap.of()); - } - @Override public ExecuteMethod getExecuteMethod() { return executeMethod; } - /** - * @see InteractsWithApps#resetApp(). - */ - @Override public void resetApp() { - execute(MobileCommand.RESET); - } - - /** - * @see InteractsWithApps#isAppInstalled(String). - */ - @Override public boolean isAppInstalled(String bundleId) { - Response response = execute(IS_APP_INSTALLED, ImmutableMap.of("bundleId", bundleId)); - - return Boolean.parseBoolean(response.getValue().toString()); - } - - /** - * @see InteractsWithApps#installApp(String). - */ - @Override public void installApp(String appPath) { - execute(INSTALL_APP, ImmutableMap.of("appPath", appPath)); - } - - /** - * @see InteractsWithApps#removeApp(String). - */ - @Override public void removeApp(String bundleId) { - execute(REMOVE_APP, ImmutableMap.of("bundleId", bundleId)); - } - - /** - * @see InteractsWithApps#launchApp(). - */ - @Override public void launchApp() { - execute(LAUNCH_APP); - } - - /** - * @see InteractsWithApps#closeApp(). - */ - @Override public void closeApp() { - execute(CLOSE_APP); - } - - /** - * @see InteractsWithApps#runAppInBackground(int). - */ - @Override public void runAppInBackground(int seconds) { - execute(RUN_APP_IN_BACKGROUND, ImmutableMap.of("seconds", seconds)); - } - - /** - * @see DeviceActionShortcuts#getDeviceTime(). - */ - @Override public String getDeviceTime() { - Response response = execute(GET_DEVICE_TIME); - return response.getValue().toString(); - } - - /** - * @see DeviceActionShortcuts#hideKeyboard(). - */ - @Override public void hideKeyboard() { - execute(HIDE_KEYBOARD); - } - - /** - * @see InteractsWithFiles#pullFile(String). - */ - @Override public byte[] pullFile(String remotePath) { - Response response = execute(PULL_FILE, ImmutableMap.of("path", remotePath)); - String base64String = response.getValue().toString(); - - return DatatypeConverter.parseBase64Binary(base64String); - } - - /** - * @see InteractsWithFiles#pullFolder(String). - */ - @Override - public byte[] pullFolder(String remotePath) { - Response response = execute(PULL_FOLDER, ImmutableMap.of("path", remotePath)); - String base64String = response.getValue().toString(); - - return DatatypeConverter.parseBase64Binary(base64String); - } - - /** - * @see PerformsTouchActions#performTouchAction(TouchAction). - */ - @SuppressWarnings("rawtypes") - @Override public TouchAction performTouchAction( - TouchAction touchAction) { - ImmutableMap parameters = touchAction.getParameters(); - execute(PERFORM_TOUCH_ACTION, parameters); - return touchAction; - } - - /** - * @see PerformsTouchActions#performMultiTouchAction(MultiTouchAction). - */ - @Override - @SuppressWarnings({"rawtypes"}) - public void performMultiTouchAction( - MultiTouchAction multiAction) { - ImmutableMap parameters = multiAction.getParameters(); - execute(PERFORM_MULTI_TOUCH, parameters); - } - /** * @see TouchShortcuts#tap(int, WebElement, int). */ @@ -604,38 +476,6 @@ protected void setSetting(AppiumSetting setting, Object value) { locationContext.setLocation(location); } - /** - * @return a map with localized strings defined in the app. - * @see HasAppStrings#getAppStringMap(). - */ - @Override public Map getAppStringMap() { - Response response = execute(GET_STRINGS); - return (Map) response.getValue(); - } - - /** - * @param language strings language code. - * @return a map with localized strings defined in the app. - * @see HasAppStrings#getAppStringMap(String). - */ - @Override public Map getAppStringMap(String language) { - Response response = execute(GET_STRINGS, prepareArguments("language", language)); - return (Map) response.getValue(); - } - - /** - * @param language strings language code. - * @param stringFile strings filename. - * @return a map with localized strings defined in the app. - * @see HasAppStrings#getAppStringMap(String, String). - */ - @Override public Map getAppStringMap(String language, String stringFile) { - String[] parameters = new String[] {"language", "stringFile"}; - Object[] values = new Object[] {language, stringFile}; - Response response = execute(GET_STRINGS, prepareArguments(parameters, values)); - return (Map) response.getValue(); - } - private TouchAction createTap(WebElement element, int duration) { TouchAction tap = new TouchAction(this); return tap.press(element).waitAction(duration).release(); diff --git a/src/main/java/io/appium/java_client/CommandExecutionHelper.java b/src/main/java/io/appium/java_client/CommandExecutionHelper.java index 393f0e388..bfa55b8cd 100644 --- a/src/main/java/io/appium/java_client/CommandExecutionHelper.java +++ b/src/main/java/io/appium/java_client/CommandExecutionHelper.java @@ -22,14 +22,13 @@ public final class CommandExecutionHelper { - public static T execute(MobileElement element, + public static T execute(ExecutesMethod executesMethod, Map.Entry> keyValuePair) { - return handleResponse(element.execute(keyValuePair.getKey(), keyValuePair.getValue())); + return handleResponse(executesMethod.execute(keyValuePair.getKey(), keyValuePair.getValue())); } - public static T execute(MobileDriver driver, - Map.Entry> keyValuePair) { - return handleResponse(driver.execute(keyValuePair.getKey(), keyValuePair.getValue())); + public static T execute(ExecutesMethod executesMethod, String command) { + return handleResponse(executesMethod.execute(command)); } private static T handleResponse(Response responce) { diff --git a/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java b/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java index 6d1ea9a03..d3cdbe1d9 100644 --- a/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java +++ b/src/main/java/io/appium/java_client/DefaultGenericMobileDriver.java @@ -16,6 +16,7 @@ package io.appium.java_client; +import com.google.common.collect.ImmutableMap; import org.openqa.selenium.By; import org.openqa.selenium.Capabilities; import org.openqa.selenium.WebDriverException; @@ -40,6 +41,10 @@ public DefaultGenericMobileDriver(CommandExecutor executor, Capabilities desired return super.execute(driverCommand, parameters); } + @Override public Response execute(String command) { + return super.execute(command, ImmutableMap.of()); + } + @Override public List findElements(By by) { return super.findElements(by); } @@ -138,20 +143,6 @@ public List findElementsByXPath(String using) { return super.findElementsByXPath(using); } - /** - * @throws WebDriverException This method is not applicable with browser/webview UI. - */ - @Override public T findElementByAccessibilityId(String using) throws WebDriverException { - return (T) findElement(MobileSelector.ACCESSIBILITY.toString(), using); - } - - /** - * @throws WebDriverException This method is not applicable with browser/webview UI. - */ - @Override public List findElementsByAccessibilityId(String using) throws WebDriverException { - return (List) findElements(MobileSelector.ACCESSIBILITY.toString(), using); - } - /** * Mouse doesn't work on mobile devices and emulators. */ diff --git a/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java b/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java index 87adcd227..07757c0fb 100644 --- a/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java +++ b/src/main/java/io/appium/java_client/DefaultGenericMobileElement.java @@ -16,6 +16,7 @@ package io.appium.java_client; +import com.google.common.collect.ImmutableMap; import org.openqa.selenium.By; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; @@ -27,12 +28,16 @@ @SuppressWarnings({"unchecked", "rawtypes"}) abstract class DefaultGenericMobileElement extends RemoteWebElement - implements FindsByAccessibilityId, TouchableElement { + implements TouchableElement { @Override public Response execute(String driverCommand, Map parameters) { return super.execute(driverCommand, parameters); } + @Override public Response execute(String command) { + return super.execute(command, ImmutableMap.of()); + } + @Override public List findElements(By by) { return super.findElements(by); } @@ -131,14 +136,6 @@ public List findElementsByXPath(String using) { return super.findElementsByXPath(using); } - @Override public T findElementByAccessibilityId(String using) { - return (T) findElement(MobileSelector.ACCESSIBILITY.toString(), using); - } - - @Override public List findElementsByAccessibilityId(String using) { - return findElements(MobileSelector.ACCESSIBILITY.toString(), using); - } - /** * @throws WebDriverException because it may not work against native app UI. */ diff --git a/src/main/java/io/appium/java_client/DeviceActionShortcuts.java b/src/main/java/io/appium/java_client/DeviceActionShortcuts.java index ce0d60569..2790bf045 100644 --- a/src/main/java/io/appium/java_client/DeviceActionShortcuts.java +++ b/src/main/java/io/appium/java_client/DeviceActionShortcuts.java @@ -16,8 +16,12 @@ package io.appium.java_client; +import static io.appium.java_client.MobileCommand.GET_DEVICE_TIME; +import static io.appium.java_client.MobileCommand.HIDE_KEYBOARD; -public interface DeviceActionShortcuts { +import org.openqa.selenium.remote.Response; + +public interface DeviceActionShortcuts extends ExecutesMethod { /** * Hides the keyboard if it is showing. @@ -25,11 +29,16 @@ public interface DeviceActionShortcuts { * Defaults to the "tapOutside" strategy (taps outside the keyboard). * Switch to using hideKeyboard(HideKeyboardStrategy.PRESS_KEY, "Done") if this doesn't work. */ - void hideKeyboard(); + default void hideKeyboard() { + execute(HIDE_KEYBOARD); + } /* Gets device date and time for both iOS(Supports only real device) and Android devices */ - String getDeviceTime(); + default String getDeviceTime() { + Response response = execute(GET_DEVICE_TIME); + return response.getValue().toString(); + } } diff --git a/src/main/java/io/appium/java_client/ExecutesMethod.java b/src/main/java/io/appium/java_client/ExecutesMethod.java new file mode 100644 index 000000000..da932b45a --- /dev/null +++ b/src/main/java/io/appium/java_client/ExecutesMethod.java @@ -0,0 +1,40 @@ +/* + * 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 java.util.Map; + +public interface ExecutesMethod { + /** + * Executes JSONWP command and returns a response + * + * @param driverCommand a JSONWP command + * @param parameters map of command parameters + * @return a result response + */ + Response execute(String driverCommand, Map parameters); + + /** + * Executes JSONWP command and returns a response + * + * @param driverCommand a JSONWP command + * @return a result response + */ + Response execute(String driverCommand); +} diff --git a/src/main/java/io/appium/java_client/FindsByAccessibilityId.java b/src/main/java/io/appium/java_client/FindsByAccessibilityId.java index 4ede49e6e..2d9e5e1cc 100644 --- a/src/main/java/io/appium/java_client/FindsByAccessibilityId.java +++ b/src/main/java/io/appium/java_client/FindsByAccessibilityId.java @@ -16,12 +16,25 @@ package io.appium.java_client; +import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; import java.util.List; -public interface FindsByAccessibilityId { - T findElementByAccessibilityId(String using); +public interface FindsByAccessibilityId extends FindsByFluentSelector { + /** + * @throws WebDriverException This method is not + * applicable with browser/webview UI. + */ + default T findElementByAccessibilityId(String using) { + return findElement(MobileSelector.ACCESSIBILITY.toString(), using); + } - List findElementsByAccessibilityId(String using); + /** + * @throws WebDriverException This method is not + * applicable with browser/webview UI. + */ + default List findElementsByAccessibilityId(String using) { + return findElements(MobileSelector.ACCESSIBILITY.toString(), using); + } } diff --git a/src/main/java/io/appium/java_client/FindsByAndroidUIAutomator.java b/src/main/java/io/appium/java_client/FindsByAndroidUIAutomator.java index e052d0c25..1fe84a79d 100644 --- a/src/main/java/io/appium/java_client/FindsByAndroidUIAutomator.java +++ b/src/main/java/io/appium/java_client/FindsByAndroidUIAutomator.java @@ -16,13 +16,26 @@ package io.appium.java_client; +import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; import java.util.List; -public interface FindsByAndroidUIAutomator { +public interface FindsByAndroidUIAutomator extends FindsByFluentSelector { - T findElementByAndroidUIAutomator(String using); + /** + * @throws WebDriverException This method is not + * applicable with browser/webview UI. + */ + default T findElementByAndroidUIAutomator(String using) { + return findElement(MobileSelector.ANDROID_UI_AUTOMATOR.toString(), using); + } - List findElementsByAndroidUIAutomator(String using); -} \ No newline at end of file + /** + * @throws WebDriverException This method is not + * applicable with browser/webview UI. + */ + default List findElementsByAndroidUIAutomator(String using) { + return findElements(MobileSelector.ANDROID_UI_AUTOMATOR.toString(), using); + } +} diff --git a/src/main/java/io/appium/java_client/FindsByIosNSPredicate.java b/src/main/java/io/appium/java_client/FindsByIosNSPredicate.java index 59c5f18d0..84bc3ff67 100644 --- a/src/main/java/io/appium/java_client/FindsByIosNSPredicate.java +++ b/src/main/java/io/appium/java_client/FindsByIosNSPredicate.java @@ -20,9 +20,13 @@ import java.util.List; -public interface FindsByIosNSPredicate { +public interface FindsByIosNSPredicate extends FindsByFluentSelector { - T findElementByIosNsPredicate(String using); + default T findElementByIosNsPredicate(String using) { + return findElement(MobileSelector.IOS_PREDICATE_STRING.toString(), using); + } - List findElementsByIosNsPredicate(String using); + default List findElementsByIosNsPredicate(String using) { + return findElements(MobileSelector.IOS_PREDICATE_STRING.toString(), using); + } } diff --git a/src/main/java/io/appium/java_client/FindsByIosUIAutomation.java b/src/main/java/io/appium/java_client/FindsByIosUIAutomation.java index 20c531bc8..32cc91246 100644 --- a/src/main/java/io/appium/java_client/FindsByIosUIAutomation.java +++ b/src/main/java/io/appium/java_client/FindsByIosUIAutomation.java @@ -16,13 +16,25 @@ package io.appium.java_client; +import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; import java.util.List; -public interface FindsByIosUIAutomation { +public interface FindsByIosUIAutomation extends FindsByFluentSelector { + /** + * @throws WebDriverException + * This method is not applicable with browser/webview UI. + */ + default T findElementByIosUIAutomation(String using) { + return findElement(MobileSelector.IOS_UI_AUTOMATION.toString(), using); + } - T findElementByIosUIAutomation(String using); - - List findElementsByIosUIAutomation(String using); -} \ No newline at end of file + /** + * @throws WebDriverException + * This method is not applicable with browser/webview UI. + */ + default List findElementsByIosUIAutomation(String using) { + return findElements(MobileSelector.IOS_UI_AUTOMATION.toString(), using); + } +} diff --git a/src/main/java/io/appium/java_client/FindsByWindowsAutomation.java b/src/main/java/io/appium/java_client/FindsByWindowsAutomation.java index 84d77ca86..6cca26d1f 100644 --- a/src/main/java/io/appium/java_client/FindsByWindowsAutomation.java +++ b/src/main/java/io/appium/java_client/FindsByWindowsAutomation.java @@ -21,7 +21,7 @@ import java.util.List; -public interface FindsByWindowsAutomation { +public interface FindsByWindowsAutomation extends FindsByFluentSelector { /** * Finds the first of elements that match the Windows UIAutomation selector supplied. @@ -29,7 +29,9 @@ public interface FindsByWindowsAutomation { * @param selector a Windows UIAutomation selector * @return The first element that matches the given selector */ - T findElementByWindowsUIAutomation(String selector); + default T findElementByWindowsUIAutomation(String selector) { + return findElement(MobileSelector.WINDOWS_UI_AUTOMATION.toString(), selector); + } /** * Finds a list of elements that match the Windows UIAutomation selector supplied. @@ -37,5 +39,7 @@ public interface FindsByWindowsAutomation { * @param selector a Windows UIAutomation selector * @return a list of elements that match the given selector */ - List findElementsByWindowsUIAutomation(String selector); + default List findElementsByWindowsUIAutomation(String selector) { + return findElements(MobileSelector.WINDOWS_UI_AUTOMATION.toString(), selector); + } } diff --git a/src/main/java/io/appium/java_client/HasAppStrings.java b/src/main/java/io/appium/java_client/HasAppStrings.java index 17a2a8de9..0c9b3905f 100644 --- a/src/main/java/io/appium/java_client/HasAppStrings.java +++ b/src/main/java/io/appium/java_client/HasAppStrings.java @@ -16,15 +16,21 @@ package io.appium.java_client; +import static io.appium.java_client.MobileCommand.GET_STRINGS; +import static io.appium.java_client.MobileCommand.prepareArguments; + +import java.util.AbstractMap; import java.util.Map; -public interface HasAppStrings { +public interface HasAppStrings extends ExecutesMethod { /** * Get all defined Strings from an app for the default language. * * @return a map with localized strings defined in the app */ - Map getAppStringMap(); + default Map getAppStringMap() { + return CommandExecutionHelper.execute(this, GET_STRINGS); + } /** * Get all defined Strings from an app for the specified language. @@ -32,7 +38,10 @@ public interface HasAppStrings { * @param language strings language code * @return a map with localized strings defined in the app */ - Map getAppStringMap(String language); + default Map getAppStringMap(String language) { + return CommandExecutionHelper.execute(this, new AbstractMap.SimpleEntry<>(GET_STRINGS, + prepareArguments("language", language))); + } /** * Get all defined Strings from an app for the specified language and @@ -42,6 +51,11 @@ public interface HasAppStrings { * @param stringFile strings filename * @return a map with localized strings defined in the app */ - Map getAppStringMap(String language, String stringFile); + default Map getAppStringMap(String language, String stringFile) { + String[] parameters = new String[] {"language", "stringFile"}; + Object[] values = new Object[] {language, stringFile}; + return CommandExecutionHelper.execute(this, + new AbstractMap.SimpleEntry<>(GET_STRINGS, prepareArguments(parameters, values))); + } } diff --git a/src/main/java/io/appium/java_client/InteractsWithApps.java b/src/main/java/io/appium/java_client/InteractsWithApps.java index 7bdbb55b4..9bf258c4c 100644 --- a/src/main/java/io/appium/java_client/InteractsWithApps.java +++ b/src/main/java/io/appium/java_client/InteractsWithApps.java @@ -16,18 +16,35 @@ package io.appium.java_client; -public interface InteractsWithApps { +import static io.appium.java_client.MobileCommand.CLOSE_APP; +import static io.appium.java_client.MobileCommand.INSTALL_APP; +import static io.appium.java_client.MobileCommand.IS_APP_INSTALLED; +import static io.appium.java_client.MobileCommand.LAUNCH_APP; +import static io.appium.java_client.MobileCommand.prepareArguments; +import static io.appium.java_client.MobileCommand.RESET; +import static io.appium.java_client.MobileCommand.REMOVE_APP; +import static io.appium.java_client.MobileCommand.RUN_APP_IN_BACKGROUND; + +import com.google.common.collect.ImmutableMap; + +import java.util.AbstractMap; + +public interface InteractsWithApps extends ExecutesMethod { /** * Launch the app which was provided in the capabilities at session creation. */ - void launchApp(); + default void launchApp() { + execute(LAUNCH_APP); + } /** * Install an app on the mobile device. * * @param appPath path to app to install. */ - void installApp(String appPath); + default void installApp(String appPath) { + execute(INSTALL_APP, ImmutableMap.of("appPath", appPath)); + } /** * Checks if an app is installed on the device. @@ -35,12 +52,17 @@ public interface InteractsWithApps { * @param bundleId bundleId of the app. * @return True if app is installed, false otherwise. */ - boolean isAppInstalled(String bundleId); + default boolean isAppInstalled(String bundleId) { + return CommandExecutionHelper.execute(this, + new AbstractMap.SimpleEntry<>(IS_APP_INSTALLED, prepareArguments("bundleId", bundleId))); + } /** * Reset the currently running app for this session. */ - void resetApp(); + default void resetApp() { + execute(RESET); + } /** * Runs the current app as a background app for the number of seconds @@ -49,18 +71,24 @@ public interface InteractsWithApps { * * @param seconds Number of seconds to run App in background. */ - void runAppInBackground(int seconds); + default void runAppInBackground(int seconds) { + execute(RUN_APP_IN_BACKGROUND, ImmutableMap.of("seconds", seconds)); + } /** * Remove the specified app from the device (uninstall). * * @param bundleId the bunble identifier (or app id) of the app to remove. */ - void removeApp(String bundleId); + default void removeApp(String bundleId) { + execute(REMOVE_APP, ImmutableMap.of("bundleId", bundleId)); + } /** * Close the app which was provided in the capabilities at session creation. */ - void closeApp(); + default void closeApp() { + execute(CLOSE_APP); + } } diff --git a/src/main/java/io/appium/java_client/InteractsWithFiles.java b/src/main/java/io/appium/java_client/InteractsWithFiles.java index 21d83f4c3..4a45d74c0 100644 --- a/src/main/java/io/appium/java_client/InteractsWithFiles.java +++ b/src/main/java/io/appium/java_client/InteractsWithFiles.java @@ -16,7 +16,15 @@ package io.appium.java_client; -public interface InteractsWithFiles { +import static io.appium.java_client.MobileCommand.PULL_FILE; +import static io.appium.java_client.MobileCommand.PULL_FOLDER; + +import com.google.common.collect.ImmutableMap; +import org.openqa.selenium.remote.Response; + +import javax.xml.bind.DatatypeConverter; + +public interface InteractsWithFiles extends ExecutesMethod { /** * @param remotePath On Android and iOS, this is either the path to the file @@ -25,7 +33,12 @@ public interface InteractsWithFiles { * the application's .app directory * @return A byte array of Base64 encoded data. */ - byte[] pullFile(String remotePath); + default byte[] pullFile(String remotePath) { + Response response = execute(PULL_FILE, ImmutableMap.of("path", remotePath)); + String base64String = response.getValue().toString(); + + return DatatypeConverter.parseBase64Binary(base64String); + } /** * Pull a folder from the simulator/device. Does not work on iOS Real @@ -38,6 +51,11 @@ public interface InteractsWithFiles { * @return A byte array of Base64 encoded data, representing a ZIP ARCHIVE * of the contents of the requested folder. */ - byte[] pullFolder(String remotePath); + default byte[] pullFolder(String remotePath) { + Response response = execute(PULL_FOLDER, ImmutableMap.of("path", remotePath)); + String base64String = response.getValue().toString(); + + return DatatypeConverter.parseBase64Binary(base64String); + } } diff --git a/src/main/java/io/appium/java_client/MobileDriver.java b/src/main/java/io/appium/java_client/MobileDriver.java index c53ccecca..bdda35e23 100644 --- a/src/main/java/io/appium/java_client/MobileDriver.java +++ b/src/main/java/io/appium/java_client/MobileDriver.java @@ -37,9 +37,7 @@ public interface MobileDriver extends WebDriver, PerformsTouchActions, ContextAware, Rotatable, FindsByAccessibilityId, LocationContext, DeviceActionShortcuts, TouchShortcuts, InteractsWithFiles, InteractsWithApps, HasAppStrings, FindsByClassName, FindsByCssSelector, FindsById, - FindsByLinkText, FindsByName, FindsByTagName, FindsByXPath, FindsByFluentSelector { - - Response execute(String driverCommand, Map parameters); + FindsByLinkText, FindsByName, FindsByTagName, FindsByXPath, FindsByFluentSelector, ExecutesMethod { List findElements(By by); diff --git a/src/main/java/io/appium/java_client/PerformsTouchActions.java b/src/main/java/io/appium/java_client/PerformsTouchActions.java index 18940735c..123811b2c 100644 --- a/src/main/java/io/appium/java_client/PerformsTouchActions.java +++ b/src/main/java/io/appium/java_client/PerformsTouchActions.java @@ -16,7 +16,13 @@ package io.appium.java_client; -public interface PerformsTouchActions { +import static io.appium.java_client.MobileCommand.PERFORM_MULTI_TOUCH; +import static io.appium.java_client.MobileCommand.PERFORM_TOUCH_ACTION; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +public interface PerformsTouchActions extends ExecutesMethod { /** * Performs a chain of touch actions, which together can be considered an * entire gesture. See the Webriver 3 spec @@ -28,7 +34,11 @@ public interface PerformsTouchActions { * touch actions to perform * @return the same touch action object */ - public TouchAction performTouchAction(TouchAction touchAction); + default TouchAction performTouchAction(TouchAction touchAction) { + ImmutableMap parameters = touchAction.getParameters(); + execute(PERFORM_TOUCH_ACTION, parameters); + return touchAction; + } /** * Performs multiple TouchAction gestures at the same time, to simulate @@ -39,5 +49,8 @@ public interface PerformsTouchActions { * * @param multiAction the MultiTouchAction object to perform. */ - public void performMultiTouchAction(MultiTouchAction multiAction); + default void performMultiTouchAction(MultiTouchAction multiAction) { + ImmutableMap parameters = multiAction.getParameters(); + execute(PERFORM_MULTI_TOUCH, parameters); + } } diff --git a/src/main/java/io/appium/java_client/TouchableElement.java b/src/main/java/io/appium/java_client/TouchableElement.java index 5773dcc43..bba550448 100644 --- a/src/main/java/io/appium/java_client/TouchableElement.java +++ b/src/main/java/io/appium/java_client/TouchableElement.java @@ -34,7 +34,8 @@ */ public interface TouchableElement extends WebElement, FindsByClassName, FindsByCssSelector, FindsById, - FindsByLinkText, FindsByName, FindsByTagName, FindsByXPath, FindsByFluentSelector { + FindsByLinkText, FindsByName, FindsByTagName, FindsByXPath, FindsByFluentSelector, FindsByAccessibilityId, + ExecutesMethod { List findElements(By by); diff --git a/src/main/java/io/appium/java_client/android/AndroidDeviceActionShortcuts.java b/src/main/java/io/appium/java_client/android/AndroidDeviceActionShortcuts.java index 866b22ebc..16b13c264 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDeviceActionShortcuts.java +++ b/src/main/java/io/appium/java_client/android/AndroidDeviceActionShortcuts.java @@ -16,6 +16,10 @@ package io.appium.java_client.android; +import static io.appium.java_client.android.AndroidMobileCommandHelper.longPressKeyCodeCommand; +import static io.appium.java_client.android.AndroidMobileCommandHelper.pressKeyCodeCommand; + +import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.DeviceActionShortcuts; public interface AndroidDeviceActionShortcuts extends DeviceActionShortcuts { @@ -25,7 +29,9 @@ public interface AndroidDeviceActionShortcuts extends DeviceActionShortcuts { * * @param key code for the key pressed on the device. */ - void pressKeyCode(int key); + default void pressKeyCode(int key) { + CommandExecutionHelper.execute(this, pressKeyCodeCommand(key)); + } /** * Send a key event along with an Android metastate to an Android device. @@ -36,14 +42,18 @@ public interface AndroidDeviceActionShortcuts extends DeviceActionShortcuts { * @see AndroidKeyCode * @see AndroidKeyMetastate */ - void pressKeyCode(int key, Integer metastate); + default void pressKeyCode(int key, Integer metastate) { + CommandExecutionHelper.execute(this, pressKeyCodeCommand(key, metastate)); + } /** * Send a long key event to the device. * * @param key code for the key pressed on the device. */ - void longPressKeyCode(int key); + default void longPressKeyCode(int key) { + CommandExecutionHelper.execute(this, longPressKeyCodeCommand(key)); + } /** * Send a long key event along with an Android metastate to an Android device. @@ -54,5 +64,7 @@ public interface AndroidDeviceActionShortcuts extends DeviceActionShortcuts { * @see AndroidKeyCode * @see AndroidKeyMetastate */ - void longPressKeyCode(int key, Integer metastate); + default void longPressKeyCode(int key, Integer metastate) { + CommandExecutionHelper.execute(this, longPressKeyCodeCommand(key, metastate)); + } } 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 91d082f94..10a1647bb 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -16,43 +16,24 @@ package io.appium.java_client.android; -import static com.google.common.base.Preconditions.checkNotNull; - -import static io.appium.java_client.android.AndroidMobileCommandHelper.currentActivityCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.endTestCoverageCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.getNetworkConnectionCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.isLockedCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.lockDeviceCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.longPressKeyCodeCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.openNotificationsCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.pressKeyCodeCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.pushFileCommandCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.setConnectionCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.startActivityCommand; import static io.appium.java_client.android.AndroidMobileCommandHelper.toggleLocationServicesCommand; -import static io.appium.java_client.android.AndroidMobileCommandHelper.unlockCommand; import io.appium.java_client.AppiumDriver; import io.appium.java_client.AppiumSetting; import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.FindsByAndroidUIAutomator; -import io.appium.java_client.MobileSelector; import io.appium.java_client.android.internal.JsonToAndroidElementConverter; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.io.FileUtils; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.http.HttpClient; -import java.io.File; -import java.io.IOException; import java.net.URL; -import java.util.List; /** * @param the required type of class which implement {@link org.openqa.selenium.WebElement}. @@ -67,7 +48,7 @@ public class AndroidDriver extends AppiumDriver implements AndroidDeviceActionShortcuts, HasNetworkConnection, PushesFiles, StartsActivity, - FindsByAndroidUIAutomator { + FindsByAndroidUIAutomator, LocksAndroidDevice { private static final String ANDROID_PLATFORM = MobilePlatform.ANDROID; @@ -187,122 +168,6 @@ public AndroidDriver(Capabilities desiredCapabilities) { doSwipe(startx, starty, endx, endy, duration); } - /** - * Send a key event to the device. - * - * @param key code for the key pressed on the device. - */ - @Override public void pressKeyCode(int key) { - CommandExecutionHelper.execute(this, pressKeyCodeCommand(key)); - } - - /** - * @param key code for the key pressed on the Android device. - * @param metastate metastate for the keypress. - * @see AndroidKeyCode - * @see AndroidKeyMetastate - * @see AndroidDeviceActionShortcuts#pressKeyCode(int, Integer). - */ - @Override public void pressKeyCode(int key, Integer metastate) { - CommandExecutionHelper.execute(this, pressKeyCodeCommand(key, metastate)); - } - - /** - * Send a long key event to the device. - * - * @param key code for the long key pressed on the device. - */ - @Override public void longPressKeyCode(int key) { - CommandExecutionHelper.execute(this, longPressKeyCodeCommand(key)); - } - - /** - * @param key code for the long key pressed on the Android device. - * @param metastate metastate for the long key press. - * @see AndroidKeyCode - * @see AndroidKeyMetastate - * @see AndroidDeviceActionShortcuts#pressKeyCode(int, Integer) - */ - @Override public void longPressKeyCode(int key, Integer metastate) { - CommandExecutionHelper.execute(this, longPressKeyCodeCommand(key, metastate)); - } - - @Override public void setConnection(Connection connection) { - CommandExecutionHelper.execute(this, setConnectionCommand(connection)); - } - - @Override public Connection getConnection() { - long bitMask = CommandExecutionHelper.execute(this, getNetworkConnectionCommand()); - Connection[] types = Connection.values(); - - for (Connection connection: types) { - if (connection.bitMask == bitMask) { - return connection; - } - } - throw new WebDriverException("The unknown network connection " - + "type has been returned. The bitmask is " + bitMask); - } - - @Override public void pushFile(String remotePath, byte[] base64Data) { - CommandExecutionHelper.execute(this, pushFileCommandCommand(remotePath, base64Data)); - } - - @Override public void pushFile(String remotePath, File file) throws IOException { - checkNotNull(file, "A reference to file should not be NULL"); - if (!file.exists()) { - throw new IOException("The given file " - + file.getAbsolutePath() + " doesn't exist"); - } - pushFile(remotePath, - Base64.encodeBase64(FileUtils.readFileToByteArray(file))); - } - - @Override public void startActivity(String appPackage, String appActivity, - String appWaitPackage, - String appWaitActivity, String intentAction, - String intentCategory, String intentFlags, - String optionalIntentArguments,boolean stopApp ) - throws IllegalArgumentException { - CommandExecutionHelper.execute(this, startActivityCommand(appPackage, appActivity, - appWaitPackage, appWaitActivity, intentAction, intentCategory, intentFlags, - optionalIntentArguments, stopApp)); - } - - - @Override - public void startActivity(String appPackage, String appActivity, - String appWaitPackage, String appWaitActivity, boolean stopApp) - throws IllegalArgumentException { - this.startActivity(appPackage,appActivity,appWaitPackage, - appWaitActivity,null,null,null,null,stopApp); - - } - - @Override public void startActivity(String appPackage, String appActivity, - String appWaitPackage, - String appWaitActivity) throws IllegalArgumentException { - - this.startActivity(appPackage, appActivity, - appWaitPackage, appWaitActivity,null,null,null,null,true); - } - - @Override public void startActivity(String appPackage, String appActivity) - throws IllegalArgumentException { - this.startActivity(appPackage, appActivity, null, null, - null,null,null,null,true); - } - - @Override public void startActivity(String appPackage, String appActivity, - String appWaitPackage, String appWaitActivity, - String intentAction,String intentCategory, - String intentFlags,String intentOptionalArgs) - throws IllegalArgumentException { - this.startActivity(appPackage,appActivity, - appWaitPackage,appWaitActivity, - intentAction,intentCategory,intentFlags,intentOptionalArgs,true); - } - /** * Get test-coverage data. * @@ -313,15 +178,6 @@ public void endTestCoverage(String intent, String path) { CommandExecutionHelper.execute(this, endTestCoverageCommand(intent, path)); } - /** - * Get the current activity being run on the mobile device. - * - * @return a current activity being run on the mobile device. - */ - public String currentActivity() { - return CommandExecutionHelper.execute(this, currentActivityCommand()); - } - /** * Open the notification shade, on Android devices. */ @@ -329,15 +185,6 @@ public void openNotifications() { CommandExecutionHelper.execute(this, openNotificationsCommand()); } - /** - * Check if the device is locked. - * - * @return true if device is locked. False otherwise - */ - public boolean isLocked() { - return CommandExecutionHelper.execute(this, isLockedCommand()); - } - public void toggleLocationServices() { CommandExecutionHelper.execute(this, toggleLocationServicesCommand()); } @@ -355,38 +202,4 @@ public void toggleLocationServices() { public void ignoreUnimportantViews(Boolean compress) { setSetting(AppiumSetting.IGNORE_UNIMPORTANT_VIEWS, compress); } - - /** - * @throws WebDriverException This method is not - * applicable with browser/webview UI. - */ - @Override - public T findElementByAndroidUIAutomator(String using) - throws WebDriverException { - return findElement(MobileSelector.ANDROID_UI_AUTOMATOR.toString(), using); - } - - /** - * @throws WebDriverException This method is not - * applicable with browser/webview UI. - */ - @Override - public List findElementsByAndroidUIAutomator(String using) - throws WebDriverException { - return findElements(MobileSelector.ANDROID_UI_AUTOMATOR.toString(), using); - } - - /** - * This method locks a device. - */ - public void lockDevice() { - CommandExecutionHelper.execute(this, lockDeviceCommand()); - } - - /** - * This method unlocks a device. - */ - public void unlockDevice() { - CommandExecutionHelper.execute(this, unlockCommand()); - } } diff --git a/src/main/java/io/appium/java_client/android/AndroidElement.java b/src/main/java/io/appium/java_client/android/AndroidElement.java index 8dd9b2825..4aad95314 100644 --- a/src/main/java/io/appium/java_client/android/AndroidElement.java +++ b/src/main/java/io/appium/java_client/android/AndroidElement.java @@ -21,32 +21,9 @@ import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.FindsByAndroidUIAutomator; import io.appium.java_client.MobileElement; -import io.appium.java_client.MobileSelector; - -import org.openqa.selenium.WebDriverException; - -import java.util.List; - public class AndroidElement extends MobileElement implements FindsByAndroidUIAutomator { - - /** - * @throws WebDriverException This method is not applicable with browser/webview UI. - */ - @Override public MobileElement findElementByAndroidUIAutomator(String using) - throws WebDriverException { - return findElement(MobileSelector.ANDROID_UI_AUTOMATOR.toString(), using); - } - - /** - * @throws WebDriverException This method is not applicable with browser/webview UI. - */ - @Override public List findElementsByAndroidUIAutomator(String using) - throws WebDriverException { - return findElements(MobileSelector.ANDROID_UI_AUTOMATOR.toString(), using); - } - /** * This method replace current text value. * @param value a new value diff --git a/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java b/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java index 2ebd75b43..65db085ee 100644 --- a/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java @@ -42,8 +42,8 @@ public class AndroidMobileCommandHelper extends MobileCommand { * {@link java.util.Map} command arguments. */ public static Map.Entry> currentActivityCommand() { - return new AbstractMap.SimpleEntry>(CURRENT_ACTIVITY, ImmutableMap.of()); + return new AbstractMap.SimpleEntry<>( + CURRENT_ACTIVITY, ImmutableMap.of()); } /** @@ -59,8 +59,8 @@ public class AndroidMobileCommandHelper extends MobileCommand { String path) { String[] parameters = new String[] {"intent", "path"}; Object[] values = new Object[] {intent, path}; - return new AbstractMap.SimpleEntry>(END_TEST_COVERAGE, prepareArguments(parameters, values)); + return new AbstractMap.SimpleEntry<>( + END_TEST_COVERAGE, prepareArguments(parameters, values)); } /** @@ -71,8 +71,8 @@ public class AndroidMobileCommandHelper extends MobileCommand { * {@link java.util.Map} command arguments. */ public static Map.Entry> getNetworkConnectionCommand() { - return new AbstractMap.SimpleEntry>(GET_NETWORK_CONNECTION, ImmutableMap.of()); + return new AbstractMap.SimpleEntry<>( + GET_NETWORK_CONNECTION, ImmutableMap.of()); } /** @@ -83,8 +83,8 @@ public class AndroidMobileCommandHelper extends MobileCommand { * {@link java.util.Map} command arguments. */ public static Map.Entry> isLockedCommand() { - return new AbstractMap.SimpleEntry>(IS_LOCKED, ImmutableMap.of()); + return new AbstractMap.SimpleEntry<>( + IS_LOCKED, ImmutableMap.of()); } /** @@ -96,8 +96,8 @@ public class AndroidMobileCommandHelper extends MobileCommand { * {@link java.util.Map} command arguments. */ public static Map.Entry> pressKeyCodeCommand(int key) { - return new AbstractMap.SimpleEntry>(PRESS_KEY_CODE, prepareArguments("keycode", key)); + return new AbstractMap.SimpleEntry<>( + PRESS_KEY_CODE, prepareArguments("keycode", key)); } /** @@ -113,8 +113,8 @@ public class AndroidMobileCommandHelper extends MobileCommand { Integer metastate) { String[] parameters = new String[] {"keycode", "metastate"}; Object[] values = new Object[] {key, metastate}; - return new AbstractMap.SimpleEntry>(PRESS_KEY_CODE, prepareArguments(parameters, values)); + return new AbstractMap.SimpleEntry<>( + PRESS_KEY_CODE, prepareArguments(parameters, values)); } /** @@ -126,8 +126,8 @@ public class AndroidMobileCommandHelper extends MobileCommand { * {@link java.util.Map} command arguments. */ public static Map.Entry> longPressKeyCodeCommand(int key) { - return new AbstractMap.SimpleEntry>(LONG_PRESS_KEY_CODE, prepareArguments("keycode", key)); + return new AbstractMap.SimpleEntry<>( + LONG_PRESS_KEY_CODE, prepareArguments("keycode", key)); } /** @@ -143,8 +143,8 @@ public class AndroidMobileCommandHelper extends MobileCommand { Integer metastate) { String[] parameters = new String[] {"keycode", "metastate"}; Object[] values = new Object[] {key, metastate}; - return new AbstractMap.SimpleEntry>(LONG_PRESS_KEY_CODE, prepareArguments(parameters, values)); + return new AbstractMap.SimpleEntry<>( + LONG_PRESS_KEY_CODE, prepareArguments(parameters, values)); } /** @@ -155,8 +155,8 @@ public class AndroidMobileCommandHelper extends MobileCommand { * {@link java.util.Map} command arguments. */ public static Map.Entry> openNotificationsCommand() { - return new AbstractMap.SimpleEntry>(OPEN_NOTIFICATIONS, ImmutableMap.of()); + return new AbstractMap.SimpleEntry<>( + OPEN_NOTIFICATIONS, ImmutableMap.of()); } /** @@ -172,8 +172,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { byte[] base64Data) { String[] parameters = new String[] {"path", "data"}; Object[] values = new Object[] {remotePath, base64Data}; - return new AbstractMap.SimpleEntry>(PUSH_FILE, prepareArguments(parameters, values)); + return new AbstractMap.SimpleEntry<>(PUSH_FILE, prepareArguments(parameters, values)); } /** @@ -188,8 +187,8 @@ public class AndroidMobileCommandHelper extends MobileCommand { String[] parameters = new String[] {"name", "parameters"}; Object[] values = new Object[] {"network_connection", ImmutableMap.of("type", connection.bitMask)}; - return new AbstractMap.SimpleEntry>(SET_NETWORK_CONNECTION, prepareArguments(parameters, values)); + return new AbstractMap.SimpleEntry<>( + SET_NETWORK_CONNECTION, prepareArguments(parameters, values)); } /** @@ -237,8 +236,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { .put("intentFlags", targetIntentFlags) .put("optionalIntentArguments", targetOptionalIntentArguments) .build(); - return new AbstractMap.SimpleEntry>(START_ACTIVITY, parameters); + return new AbstractMap.SimpleEntry<>(START_ACTIVITY, parameters); } /** @@ -249,8 +247,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * {@link java.util.Map} command arguments. */ public static Map.Entry> toggleLocationServicesCommand() { - return new AbstractMap.SimpleEntry>(TOGGLE_LOCATION_SERVICES, ImmutableMap.of()); + return new AbstractMap.SimpleEntry<>(TOGGLE_LOCATION_SERVICES, ImmutableMap.of()); } /** @@ -261,8 +258,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * {@link java.util.Map} command arguments. */ public static Map.Entry> unlockCommand() { - return new AbstractMap.SimpleEntry>(UNLOCK, ImmutableMap.of()); + return new AbstractMap.SimpleEntry<>(UNLOCK, ImmutableMap.of()); } /** @@ -273,8 +269,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { * {@link java.util.Map} command arguments. */ public static Map.Entry> lockDeviceCommand() { - return new AbstractMap.SimpleEntry>(LOCK, prepareArguments("seconds", 0)); + return new AbstractMap.SimpleEntry<>(LOCK, prepareArguments("seconds", 0)); } /** @@ -292,7 +287,7 @@ public class AndroidMobileCommandHelper extends MobileCommand { Object[] values = new Object[] {hasIdentityObject.getId(), value}; - return new AbstractMap.SimpleEntry>(REPLACE_VALUE, prepareArguments(parameters, values)); + return new AbstractMap.SimpleEntry<>( + REPLACE_VALUE, prepareArguments(parameters, values)); } } diff --git a/src/main/java/io/appium/java_client/android/HasNetworkConnection.java b/src/main/java/io/appium/java_client/android/HasNetworkConnection.java index 4143d6995..fde98c3b5 100644 --- a/src/main/java/io/appium/java_client/android/HasNetworkConnection.java +++ b/src/main/java/io/appium/java_client/android/HasNetworkConnection.java @@ -16,14 +16,23 @@ package io.appium.java_client.android; -public interface HasNetworkConnection { +import static io.appium.java_client.android.AndroidMobileCommandHelper.getNetworkConnectionCommand; +import static io.appium.java_client.android.AndroidMobileCommandHelper.setConnectionCommand; + +import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecutesMethod; +import org.openqa.selenium.WebDriverException; + +public interface HasNetworkConnection extends ExecutesMethod { /** * Set the network connection of the device. * * @param connection The bitmask of the desired connection */ - void setConnection(Connection connection); + default void setConnection(Connection connection) { + CommandExecutionHelper.execute(this, setConnectionCommand(connection)); + } /** @@ -32,5 +41,16 @@ public interface HasNetworkConnection { * @return Connection object will let you inspect the status * of None, AirplaneMode, Wifi, Data and All connections */ - Connection getConnection(); + default Connection getConnection() { + long bitMask = CommandExecutionHelper.execute(this, getNetworkConnectionCommand()); + Connection[] types = Connection.values(); + + for (Connection connection: types) { + if (connection.bitMask == bitMask) { + return connection; + } + } + throw new WebDriverException("The unknown network connection " + + "type has been returned. The bitmask is " + bitMask); + } } diff --git a/src/main/java/io/appium/java_client/android/LocksAndroidDevice.java b/src/main/java/io/appium/java_client/android/LocksAndroidDevice.java new file mode 100644 index 000000000..282f0e2da --- /dev/null +++ b/src/main/java/io/appium/java_client/android/LocksAndroidDevice.java @@ -0,0 +1,49 @@ +/* + * 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.android; + +import static io.appium.java_client.android.AndroidMobileCommandHelper.isLockedCommand; +import static io.appium.java_client.android.AndroidMobileCommandHelper.lockDeviceCommand; +import static io.appium.java_client.android.AndroidMobileCommandHelper.unlockCommand; + +import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecutesMethod; + +public interface LocksAndroidDevice extends ExecutesMethod { + /** + * Check if the device is locked. + * + * @return true if device is locked. False otherwise + */ + default boolean isLocked() { + return CommandExecutionHelper.execute(this, isLockedCommand()); + } + + /** + * This method locks a device. + */ + default void lockDevice() { + CommandExecutionHelper.execute(this, lockDeviceCommand()); + } + + /** + * This method unlocks a device. + */ + default void unlockDevice() { + CommandExecutionHelper.execute(this, unlockCommand()); + } +} diff --git a/src/main/java/io/appium/java_client/android/PushesFiles.java b/src/main/java/io/appium/java_client/android/PushesFiles.java index b258d0196..e9708e5fa 100644 --- a/src/main/java/io/appium/java_client/android/PushesFiles.java +++ b/src/main/java/io/appium/java_client/android/PushesFiles.java @@ -16,12 +16,19 @@ package io.appium.java_client.android; +import static com.google.common.base.Preconditions.checkNotNull; +import static io.appium.java_client.android.AndroidMobileCommandHelper.pushFileCommandCommand; + +import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecutesMethod; import io.appium.java_client.InteractsWithFiles; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; -public interface PushesFiles extends InteractsWithFiles { +public interface PushesFiles extends InteractsWithFiles, ExecutesMethod { /** * Saves base64 encoded data as a file on the remote mobile device. @@ -29,7 +36,9 @@ public interface PushesFiles extends InteractsWithFiles { * @param remotePath Path to file to write data to on remote device * @param base64Data Base64 encoded byte array of data to write to remote device */ - void pushFile(String remotePath, byte[] base64Data); + default void pushFile(String remotePath, byte[] base64Data) { + CommandExecutionHelper.execute(this, pushFileCommandCommand(remotePath, base64Data)); + } /** * Saves given file as a file on the remote mobile device. @@ -38,6 +47,14 @@ public interface PushesFiles extends InteractsWithFiles { * @param file is a file to write to remote device * @throws IOException when there are problems with a file or current file system */ - void pushFile(String remotePath, File file) throws IOException; + default void pushFile(String remotePath, File file) throws IOException { + checkNotNull(file, "A reference to file should not be NULL"); + if (!file.exists()) { + throw new IOException("The given file " + + file.getAbsolutePath() + " doesn't exist"); + } + pushFile(remotePath, + Base64.encodeBase64(FileUtils.readFileToByteArray(file))); + } } diff --git a/src/main/java/io/appium/java_client/android/StartsActivity.java b/src/main/java/io/appium/java_client/android/StartsActivity.java index 6baf03aa0..46ea81f30 100644 --- a/src/main/java/io/appium/java_client/android/StartsActivity.java +++ b/src/main/java/io/appium/java_client/android/StartsActivity.java @@ -16,7 +16,13 @@ package io.appium.java_client.android; -public interface StartsActivity { +import static io.appium.java_client.android.AndroidMobileCommandHelper.currentActivityCommand; +import static io.appium.java_client.android.AndroidMobileCommandHelper.startActivityCommand; + +import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecutesMethod; + +public interface StartsActivity extends ExecutesMethod { /** * This method should start arbitrary activity during a test. If the activity belongs to * another application, that application is started and the activity is opened. @@ -27,8 +33,11 @@ public interface StartsActivity { * @param appWaitActivity Automation will begin after this activity starts. [Optional] * @param stopApp If true, target app will be stopped. [Optional] */ - void startActivity(String appPackage, String appActivity, String appWaitPackage, - String appWaitActivity, boolean stopApp) throws IllegalArgumentException; + default void startActivity(String appPackage, String appActivity, String appWaitPackage, + String appWaitActivity, boolean stopApp) throws IllegalArgumentException { + this.startActivity(appPackage,appActivity,appWaitPackage, + appWaitActivity,null,null,null,null,stopApp); + } /** * This method should start arbitrary activity during a test. If the activity belongs to @@ -39,8 +48,11 @@ void startActivity(String appPackage, String appActivity, String appWaitPackage, * @param appWaitPackage Automation will begin after this package starts. [Optional] * @param appWaitActivity Automation will begin after this activity starts. [Optional] */ - void startActivity(String appPackage, String appActivity, String appWaitPackage, - String appWaitActivity) throws IllegalArgumentException; + default void startActivity(String appPackage, String appActivity, String appWaitPackage, + String appWaitActivity) throws IllegalArgumentException { + this.startActivity(appPackage, appActivity, + appWaitPackage, appWaitActivity,null,null,null,null,true); + } /** * This method should start arbitrary activity during a test. If the activity belongs to @@ -49,7 +61,10 @@ void startActivity(String appPackage, String appActivity, String appWaitPackage, * @param appPackage The package containing the activity. [Required] * @param appActivity The activity to start. [Required] */ - void startActivity(String appPackage, String appActivity) throws IllegalArgumentException; + default void startActivity(String appPackage, String appActivity) throws IllegalArgumentException { + this.startActivity(appPackage, appActivity, null, null, + null,null,null,null,true); + } /** * This method should start arbitrary activity during a test. If the activity belongs to @@ -65,11 +80,15 @@ void startActivity(String appPackage, String appActivity, String appWaitPackage, * @param intentOptionalArgs Additional intent arguments that will be used to * start activity [Optional] */ - void startActivity(String appPackage, String appActivity, - String appWaitPackage, String appWaitActivity, - String intentAction, String intentCategory, - String intentFlags, String intentOptionalArgs) - throws IllegalArgumentException; + default void startActivity(String appPackage, String appActivity, + String appWaitPackage, String appWaitActivity, + String intentAction, String intentCategory, + String intentFlags, String intentOptionalArgs) + throws IllegalArgumentException { + this.startActivity(appPackage,appActivity, + appWaitPackage,appWaitActivity, + intentAction,intentCategory,intentFlags,intentOptionalArgs,true); + } /** * This method should start arbitrary activity during a test. If the activity belongs to @@ -86,10 +105,22 @@ void startActivity(String appPackage, String appActivity, * start activity [Optional] * @param stopApp If true, target app will be stopped. [Optional] */ - void startActivity(String appPackage, String appActivity, String appWaitPackage, - String appWaitActivity, String intentAction, - String intentCategory, String intentFlags, - String optionalIntentArguments,boolean stopApp ) - throws IllegalArgumentException; + default void startActivity(String appPackage, String appActivity, String appWaitPackage, + String appWaitActivity, String intentAction, + String intentCategory, String intentFlags, + String optionalIntentArguments,boolean stopApp ) + throws IllegalArgumentException { + CommandExecutionHelper.execute(this, startActivityCommand(appPackage, appActivity, + appWaitPackage, appWaitActivity, intentAction, intentCategory, intentFlags, + optionalIntentArguments, stopApp)); + } + /** + * Get the current activity being run on the mobile device. + * + * @return a current activity being run on the mobile device. + */ + default String currentActivity() { + return CommandExecutionHelper.execute(this, currentActivityCommand()); + } } diff --git a/src/main/java/io/appium/java_client/ios/IOSDeviceActionShortcuts.java b/src/main/java/io/appium/java_client/ios/IOSDeviceActionShortcuts.java index 0916bb672..7a5385866 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDeviceActionShortcuts.java +++ b/src/main/java/io/appium/java_client/ios/IOSDeviceActionShortcuts.java @@ -16,8 +16,12 @@ package io.appium.java_client.ios; +import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.DeviceActionShortcuts; +import static io.appium.java_client.ios.IOSMobileCommandHelper.hideKeyboardCommand; +import static io.appium.java_client.ios.IOSMobileCommandHelper.shakeCommand; + public interface IOSDeviceActionShortcuts extends DeviceActionShortcuts { /** @@ -27,7 +31,9 @@ public interface IOSDeviceActionShortcuts extends DeviceActionShortcuts { * @param keyName The button pressed by the mobile driver to attempt hiding the * keyboard. */ - void hideKeyboard(String keyName); + default void hideKeyboard(String keyName) { + CommandExecutionHelper.execute(this, hideKeyboardCommand(keyName)); + } /** * Hides the keyboard if it is showing. Available strategies are PRESS_KEY @@ -40,11 +46,15 @@ public interface IOSDeviceActionShortcuts extends DeviceActionShortcuts { * @param keyName a String, representing the text displayed on the button of the * keyboard you want to press. For example: "Done". */ - void hideKeyboard(String strategy, String keyName); + default void hideKeyboard(String strategy, String keyName) { + CommandExecutionHelper.execute(this, hideKeyboardCommand(strategy, keyName)); + } /** * Simulate shaking the device. */ - void shake(); + default void shake() { + CommandExecutionHelper.execute(this, shakeCommand()); + } } diff --git a/src/main/java/io/appium/java_client/ios/IOSDriver.java b/src/main/java/io/appium/java_client/ios/IOSDriver.java index 24d633d45..518f186a1 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -17,21 +17,15 @@ package io.appium.java_client.ios; import static io.appium.java_client.MobileCommand.prepareArguments; -import static io.appium.java_client.ios.IOSMobileCommandHelper.hideKeyboardCommand; -import static io.appium.java_client.ios.IOSMobileCommandHelper.lockDeviceCommand; -import static io.appium.java_client.ios.IOSMobileCommandHelper.shakeCommand; import io.appium.java_client.AppiumDriver; -import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.FindsByIosUIAutomation; -import io.appium.java_client.MobileSelector; import io.appium.java_client.ios.internal.JsonToIOSElementConverter; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import org.openqa.selenium.Alert; import org.openqa.selenium.Capabilities; -import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.HttpCommandExecutor; @@ -40,7 +34,6 @@ import org.openqa.selenium.security.Credentials; import java.net.URL; -import java.util.List; /** @@ -57,7 +50,7 @@ public class IOSDriver extends AppiumDriver implements IOSDeviceActionShortcuts, - FindsByIosUIAutomation { + FindsByIosUIAutomation, LocksIOSDevice { private static final String IOS_PLATFORM = MobilePlatform.IOS; @@ -177,56 +170,6 @@ public IOSDriver(Capabilities desiredCapabilities) { doSwipe(startx, starty, endx - startx, endy - starty, duration); } - /** - * @see IOSDeviceActionShortcuts#hideKeyboard(String, String). - */ - @Override public void hideKeyboard(String strategy, String keyName) { - CommandExecutionHelper.execute(this, hideKeyboardCommand(strategy, keyName)); - } - - /** - * @see IOSDeviceActionShortcuts#hideKeyboard(String). - */ - @Override public void hideKeyboard(String keyName) { - CommandExecutionHelper.execute(this, hideKeyboardCommand(keyName)); - } - - /** - * @see IOSDeviceActionShortcuts#shake(). - */ - @Override public void shake() { - CommandExecutionHelper.execute(this, shakeCommand()); - } - - /** - * @throws WebDriverException - * This method is not applicable with browser/webview UI. - */ - @Override - public T findElementByIosUIAutomation(String using) - throws WebDriverException { - return findElement(MobileSelector.IOS_UI_AUTOMATION.toString(), using); - } - - /** - * @throws WebDriverException This method is not applicable with browser/webview UI. - */ - @Override - public List findElementsByIosUIAutomation(String using) - throws WebDriverException { - return findElements(MobileSelector.IOS_UI_AUTOMATION.toString(), using); - } - - /** - * Lock the device (bring it to the lock screen) for a given number of - * seconds. - * - * @param seconds number of seconds to lock the screen for - */ - public void lockDevice(int seconds) { - CommandExecutionHelper.execute(this, lockDeviceCommand(seconds)); - } - @Override public TargetLocator switchTo() { return new InnerTargetLocator(); } diff --git a/src/main/java/io/appium/java_client/ios/IOSElement.java b/src/main/java/io/appium/java_client/ios/IOSElement.java index 86cd3ab0b..cac1b54f3 100644 --- a/src/main/java/io/appium/java_client/ios/IOSElement.java +++ b/src/main/java/io/appium/java_client/ios/IOSElement.java @@ -18,28 +18,7 @@ import io.appium.java_client.FindsByIosUIAutomation; import io.appium.java_client.MobileElement; -import io.appium.java_client.MobileSelector; -import org.openqa.selenium.WebDriverException; - -import java.util.List; public class IOSElement extends MobileElement implements FindsByIosUIAutomation { - /** - * @throws WebDriverException - * This method is not applicable with browser/webview UI. - */ - @Override public MobileElement findElementByIosUIAutomation(String using) - throws WebDriverException { - return findElement(MobileSelector.IOS_UI_AUTOMATION.toString(), using); - } - - /** - * @throws WebDriverException - * This method is not applicable with browser/webview UI. - */ - @Override public List findElementsByIosUIAutomation(String using) - throws WebDriverException { - return findElements(MobileSelector.IOS_UI_AUTOMATION.toString(), using); - } } diff --git a/src/main/java/io/appium/java_client/ios/IOSMobileCommandHelper.java b/src/main/java/io/appium/java_client/ios/IOSMobileCommandHelper.java index 4de1bb8c7..20f12b08a 100644 --- a/src/main/java/io/appium/java_client/ios/IOSMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/ios/IOSMobileCommandHelper.java @@ -35,8 +35,8 @@ public class IOSMobileCommandHelper extends MobileCommand { * {@link java.util.Map} command arguments. */ public static Map.Entry> hideKeyboardCommand(String keyName) { - return new AbstractMap.SimpleEntry>(HIDE_KEYBOARD, prepareArguments("keyName", keyName)); + return new AbstractMap.SimpleEntry<>( + HIDE_KEYBOARD, prepareArguments("keyName", keyName)); } /** @@ -53,8 +53,8 @@ public class IOSMobileCommandHelper extends MobileCommand { String keyName) { String[] parameters = new String[] {"strategy", "key"}; Object[] values = new Object[] {strategy, keyName}; - return new AbstractMap.SimpleEntry>(HIDE_KEYBOARD, prepareArguments(parameters, values)); + return new AbstractMap.SimpleEntry<>( + HIDE_KEYBOARD, prepareArguments(parameters, values)); } /** @@ -66,8 +66,8 @@ public class IOSMobileCommandHelper extends MobileCommand { * {@link java.util.Map} command arguments. */ public static Map.Entry> lockDeviceCommand(int seconds) { - return new AbstractMap.SimpleEntry>(LOCK, prepareArguments("seconds", seconds)); + return new AbstractMap.SimpleEntry<>( + LOCK, prepareArguments("seconds", seconds)); } /** @@ -78,7 +78,7 @@ public class IOSMobileCommandHelper extends MobileCommand { * {@link java.util.Map} command arguments. */ public static Map.Entry> shakeCommand() { - return new AbstractMap.SimpleEntry>(SHAKE, ImmutableMap.of()); + return new AbstractMap.SimpleEntry<>( + SHAKE, ImmutableMap.of()); } } diff --git a/src/main/java/io/appium/java_client/ios/LocksIOSDevice.java b/src/main/java/io/appium/java_client/ios/LocksIOSDevice.java new file mode 100644 index 000000000..e8586cb22 --- /dev/null +++ b/src/main/java/io/appium/java_client/ios/LocksIOSDevice.java @@ -0,0 +1,34 @@ +/* + * 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.ios; + +import static io.appium.java_client.ios.IOSMobileCommandHelper.lockDeviceCommand; + +import io.appium.java_client.CommandExecutionHelper; +import io.appium.java_client.ExecutesMethod; + +public interface LocksIOSDevice extends ExecutesMethod { + /** + * Lock the device (bring it to the lock screen) for a given number of + * seconds. + * + * @param seconds number of seconds to lock the screen for + */ + default void lockDevice(int seconds) { + CommandExecutionHelper.execute(this, lockDeviceCommand(seconds)); + } +} diff --git a/src/test/java/io/appium/java_client/events/FewInstancesTest.java b/src/test/java/io/appium/java_client/events/FewInstancesTest.java index 7eeb4fbdc..54a6cc8f6 100644 --- a/src/test/java/io/appium/java_client/events/FewInstancesTest.java +++ b/src/test/java/io/appium/java_client/events/FewInstancesTest.java @@ -1,8 +1,8 @@ package io.appium.java_client.events; -import static com.thoughtworks.selenium.SeleneseTestCase.assertNotEquals; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertNotEquals; import io.appium.java_client.events.listeners.AlertListener; import io.appium.java_client.events.listeners.ContextListener;