diff --git a/build.gradle b/build.gradle index 1e5b85b5f..9ba72cc99 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ compileJava { } dependencies { - compile('org.seleniumhq.selenium:selenium-java:2.53.1'){ + compile('org.seleniumhq.selenium:selenium-java:3.0.0'){ exclude module: 'cglib' exclude group: 'com.google.code.gson' } @@ -60,6 +60,7 @@ dependencies { compile 'cglib:cglib:3.2.4' compile 'commons-validator:commons-validator:1.5.1' compile 'org.apache.commons:commons-lang3:3.4' + compile 'commons-io:commons-io:2.5' compile 'com.google.code.gson:gson:2.6.2' compile 'org.springframework:spring-context:4.3.2.RELEASE' compile 'org.aspectj:aspectjweaver:1.8.9' diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 843aa3751..2eacf2e1f 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -30,6 +30,7 @@ import org.openqa.selenium.By; import org.openqa.selenium.Capabilities; +import org.openqa.selenium.DeviceRotation; import org.openqa.selenium.Dimension; import org.openqa.selenium.Point; import org.openqa.selenium.ScreenOrientation; @@ -57,17 +58,18 @@ import java.util.Map; import java.util.Set; + /** -* @param the required type of class which implement {@link org.openqa.selenium.WebElement}. - * Instances of the defined type will be returned via findElement* and findElements* - * Warning (!!!). Allowed types: - * {@link org.openqa.selenium.WebElement} - * {@link io.appium.java_client.TouchableElement} - * {@link org.openqa.selenium.remote.RemoteWebElement} - * {@link io.appium.java_client.MobileElement} and its subclasses that designed - * specifically - * for each target mobile OS (still Android and iOS) -*/ + * @param the required type of class which implement {@link org.openqa.selenium.WebElement}. + * Instances of the defined type will be returned via findElement* and findElements* + * Warning (!!!). Allowed types: + * {@link org.openqa.selenium.WebElement} + * {@link io.appium.java_client.TouchableElement} + * {@link org.openqa.selenium.remote.RemoteWebElement} + * {@link io.appium.java_client.MobileElement} and its subclasses that designed + * specifically + * for each target mobile OS (still Android and iOS) + */ @SuppressWarnings("unchecked") public abstract class AppiumDriver extends DefaultGenericMobileDriver { @@ -79,13 +81,13 @@ public abstract class AppiumDriver private ExecuteMethod executeMethod; /** - * @param executor is an instance of {@link org.openqa.selenium.remote.HttpCommandExecutor} - * or class that extends it. Default commands or another vendor-specific - * commands may be specified there. - * @param capabilities take a look - * at {@link org.openqa.selenium.Capabilities} + * @param executor is an instance of {@link org.openqa.selenium.remote.HttpCommandExecutor} + * or class that extends it. Default commands or another vendor-specific + * commands may be specified there. + * @param capabilities take a look + * at {@link org.openqa.selenium.Capabilities} * @param converterClazz is an instance of a class that extends - * {@link org.openqa.selenium.remote.internal.JsonToWebElementConverter}. It converts + * {@link org.openqa.selenium.remote.internal.JsonToWebElementConverter}. It converts * JSON response to an instance of * {@link org.openqa.selenium.WebElement} */ @@ -98,10 +100,10 @@ protected AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities, this.remoteAddress = executor.getAddressOfRemoteServer(); try { Constructor constructor = - converterClazz.getConstructor(RemoteWebDriver.class); + converterClazz.getConstructor(RemoteWebDriver.class); this.setElementConverter(constructor.newInstance(this)); } catch (NoSuchMethodException | IllegalAccessException | InstantiationException - | InvocationTargetException e) { + | InvocationTargetException e) { throw new RuntimeException(e); } } @@ -114,7 +116,7 @@ public AppiumDriver(URL remoteAddress, Capabilities desiredCapabilities, public AppiumDriver(URL remoteAddress, HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities, - Class converterClazz) { + Class converterClazz) { this(new AppiumCommandExecutor(MobileCommand.commandRepository, remoteAddress, httpClientFactory), desiredCapabilities, converterClazz); } @@ -127,7 +129,7 @@ public AppiumDriver(AppiumDriverLocalService service, Capabilities desiredCapabi public AppiumDriver(AppiumDriverLocalService service, HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities, - Class converterClazz) { + Class converterClazz) { this(new AppiumCommandExecutor(MobileCommand.commandRepository, service, httpClientFactory), desiredCapabilities, converterClazz); } @@ -139,14 +141,14 @@ public AppiumDriver(AppiumServiceBuilder builder, Capabilities desiredCapabiliti public AppiumDriver(AppiumServiceBuilder builder, HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities, - Class converterClazz) { + Class converterClazz) { this(builder.build(), httpClientFactory, desiredCapabilities, converterClazz); } public AppiumDriver(HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities, Class converterClazz) { - this(AppiumDriverLocalService.buildDefaultService(), httpClientFactory, - desiredCapabilities, converterClazz); + this(AppiumDriverLocalService.buildDefaultService(), httpClientFactory, desiredCapabilities, + converterClazz); } public AppiumDriver(Capabilities desiredCapabilities, @@ -156,8 +158,8 @@ public AppiumDriver(Capabilities desiredCapabilities, /** * @param originalCapabilities the given {@link Capabilities}. - * @param newPlatform a {@link MobileCapabilityType#PLATFORM_NAME} value which has - * to be set up + * @param newPlatform a {@link MobileCapabilityType#PLATFORM_NAME} value which has + * to be set up * @return {@link Capabilities} with changed mobile platform value */ protected static Capabilities substituteMobilePlatform(Capabilities originalCapabilities, @@ -409,6 +411,21 @@ public void zoom(int x, int y) { return contextName; } + @Override public DeviceRotation rotation() { + Response response = execute(DriverCommand.GET_SCREEN_ROTATION); + DeviceRotation deviceRotation = + new DeviceRotation((Map) response.getValue()); + if (deviceRotation.getX() < 0 || deviceRotation.getY() < 0 || deviceRotation.getZ() < 0) { + throw new WebDriverException("Unexpected orientation returned: " + deviceRotation); + } + return deviceRotation; + } + + @Override public void rotate(DeviceRotation rotation) { + execute(DriverCommand.SET_SCREEN_ROTATION, rotation.parameters()); + } + + @Override public void rotate(ScreenOrientation orientation) { execute(DriverCommand.SET_SCREEN_ORIENTATION, ImmutableMap.of("orientation", orientation.value().toUpperCase())); @@ -450,7 +467,6 @@ public URL getRemoteAddress() { /** * @return a map with values that hold session details. - * */ public Map getSessionDetails() { Response response = execute(GET_SESSION); diff --git a/src/main/java/io/appium/java_client/events/DefaultListener.java b/src/main/java/io/appium/java_client/events/DefaultListener.java index e33b11eb2..c42e6cb4d 100644 --- a/src/main/java/io/appium/java_client/events/DefaultListener.java +++ b/src/main/java/io/appium/java_client/events/DefaultListener.java @@ -42,19 +42,18 @@ import java.util.Collection; import java.util.List; -class DefaultListener implements Listener, AppiumWebDriverEventListener, ListensToException, - SearchingEventListener, NavigationEventListener, - JavaScriptEventListener, ElementEventListener, AlertEventListener, +class DefaultListener + implements Listener, AppiumWebDriverEventListener, ListensToException, SearchingEventListener, + NavigationEventListener, JavaScriptEventListener, ElementEventListener, AlertEventListener, WindowEventListener, ContextEventListener, RotationEventListener { private final List listeners = new ArrayList<>(); - private Object dispatcher = Proxy.newProxyInstance(Listener.class.getClassLoader(), - new Class[] {AlertEventListener.class, - ContextEventListener.class, ElementEventListener.class, JavaScriptEventListener.class, - ListensToException.class, NavigationEventListener.class, RotationEventListener.class, - SearchingEventListener.class, WindowEventListener.class, - WebDriverEventListener.class}, + private Object dispatcher = Proxy.newProxyInstance(Listener.class.getClassLoader(), + new Class[] {AlertEventListener.class, ContextEventListener.class, + ElementEventListener.class, JavaScriptEventListener.class, ListensToException.class, + NavigationEventListener.class, RotationEventListener.class, + SearchingEventListener.class, WindowEventListener.class, WebDriverEventListener.class}, new ListenerInvocationHandler(listeners)); @Override public void beforeNavigateTo(String url, WebDriver driver) { @@ -109,10 +108,20 @@ class DefaultListener implements Listener, AppiumWebDriverEventListener, Listens ((ElementEventListener) dispatcher).beforeChangeValueOf(element, driver); } + @Override public void beforeChangeValueOf(WebElement element, WebDriver driver, + CharSequence[] keysToSend) { + ((ElementEventListener) dispatcher).beforeChangeValueOf(element, driver, keysToSend); + } + @Override public void afterChangeValueOf(WebElement element, WebDriver driver) { ((ElementEventListener) dispatcher).afterChangeValueOf(element, driver); } + @Override public void afterChangeValueOf(WebElement element, WebDriver driver, + CharSequence[] keysToSend) { + ((ElementEventListener) dispatcher).afterChangeValueOf(element, driver, keysToSend); + } + @Override public void beforeScript(String script, WebDriver driver) { ((JavaScriptEventListener) dispatcher).beforeScript(script, driver); } @@ -206,4 +215,4 @@ public void afterWindowIsMoved(WebDriver driver, WebDriver.Window window, Point @Override public void afterRotation(WebDriver driver, ScreenOrientation orientation) { ((RotationEventListener) dispatcher).afterRotation(driver, orientation); } -} +} \ No newline at end of file diff --git a/src/main/java/io/appium/java_client/events/api/general/ElementEventListener.java b/src/main/java/io/appium/java_client/events/api/general/ElementEventListener.java index 83a521da8..960d7f5b6 100644 --- a/src/main/java/io/appium/java_client/events/api/general/ElementEventListener.java +++ b/src/main/java/io/appium/java_client/events/api/general/ElementEventListener.java @@ -47,6 +47,15 @@ public interface ElementEventListener extends Listener { */ void beforeChangeValueOf(WebElement element, WebDriver driver); + /** + * Called before {@link org.openqa.selenium.WebElement#clear WebElement.clear()}, + * {@link org.openqa.selenium.WebElement#sendKeys WebElement.sendKeys(...)}. + * + * @param driver WebDriver + * @param element the WebElement being used for the action + */ + void beforeChangeValueOf(WebElement element, WebDriver driver, CharSequence[] keysToSend); + /** * Called after {@link org.openqa.selenium.WebElement#clear WebElement.clear()}, * {@link org.openqa.selenium.WebElement#sendKeys WebElement.sendKeys(...)} . @@ -56,4 +65,14 @@ public interface ElementEventListener extends Listener { * @param element the WebElement being used for the action */ void afterChangeValueOf(WebElement element, WebDriver driver); -} + + /** + * Called after {@link org.openqa.selenium.WebElement#clear WebElement.clear()}, + * {@link org.openqa.selenium.WebElement#sendKeys WebElement.sendKeys(...)} . + * Not called, if an exception is thrown. + * + * @param driver WebDriver + * @param element the WebElement being used for the action + */ + void afterChangeValueOf(WebElement element, WebDriver driver, CharSequence[] keysToSend); +} \ No newline at end of file diff --git a/src/test/java/io/appium/java_client/events/EmptyWebDriver.java b/src/test/java/io/appium/java_client/events/EmptyWebDriver.java index 2e5f308ad..3caa873e3 100644 --- a/src/test/java/io/appium/java_client/events/EmptyWebDriver.java +++ b/src/test/java/io/appium/java_client/events/EmptyWebDriver.java @@ -13,6 +13,7 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.ContextAware; import org.openqa.selenium.Cookie; +import org.openqa.selenium.DeviceRotation; import org.openqa.selenium.HasCapabilities; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.NoSuchElementException; @@ -61,10 +62,18 @@ private static List createStubList() { //The rotation does nothing there } + @Override public void rotate(DeviceRotation rotation) { + //The rotation does nothing there + } + @Override public ScreenOrientation getOrientation() { return null; } + @Override public DeviceRotation rotation() { + return null; + } + @Override public void get(String url) { //There is no navigation. It is added only for event firing } diff --git a/src/test/java/io/appium/java_client/events/listeners/AppiumListener.java b/src/test/java/io/appium/java_client/events/listeners/AppiumListener.java index cd3f06c77..4224dc529 100644 --- a/src/test/java/io/appium/java_client/events/listeners/AppiumListener.java +++ b/src/test/java/io/appium/java_client/events/listeners/AppiumListener.java @@ -63,6 +63,11 @@ public class AppiumListener extends TestListener implements AppiumWebDriverEvent messages.add("WebDriverEventListener: Thee element was clicked"); } + @Override public void beforeChangeValueOf(WebElement element, WebDriver driver, + CharSequence[] keysToSend) { + messages.add("WebDriverEventListener: Attempt to click on the element"); + } + @Override public void beforeChangeValueOf(WebElement element, WebDriver driver) { messages.add("WebDriverEventListener: Attempt to change value of the element"); } @@ -71,6 +76,11 @@ public class AppiumListener extends TestListener implements AppiumWebDriverEvent messages.add("WebDriverEventListener: The value of the element was changed"); } + @Override public void afterChangeValueOf(WebElement element, WebDriver driver, + CharSequence[] keysToSend) { + messages.add("WebDriverEventListener: Thee element was clicked"); + } + @Override public void beforeScript(String script, WebDriver driver) { messages.add("WebDriverEventListener: Attempt to perform java script: " + script); } diff --git a/src/test/java/io/appium/java_client/events/listeners/ElementListener.java b/src/test/java/io/appium/java_client/events/listeners/ElementListener.java index 8b9d50ec3..c33caf990 100644 --- a/src/test/java/io/appium/java_client/events/listeners/ElementListener.java +++ b/src/test/java/io/appium/java_client/events/listeners/ElementListener.java @@ -18,10 +18,20 @@ public class ElementListener extends TestListener implements ElementEventListene messages.add("Attempt to change value of the element"); } + @Override public void beforeChangeValueOf(WebElement element, WebDriver driver, + CharSequence[] keysToSend) { + messages.add("Attempt to change value of the element"); + } + @Override public void afterChangeValueOf(WebElement element, WebDriver driver) { messages.add("The value of the element was changed"); } + @Override public void afterChangeValueOf(WebElement element, WebDriver driver, + CharSequence[] keysToSend) { + messages.add("The value of the element was changed"); + } + @Override protected void add() { SingleListeners.listeners.put(ElementListener.class, this); } diff --git a/src/test/java/io/appium/java_client/events/listeners/ElementListener2.java b/src/test/java/io/appium/java_client/events/listeners/ElementListener2.java index 8add3bf69..6fb5cc55c 100644 --- a/src/test/java/io/appium/java_client/events/listeners/ElementListener2.java +++ b/src/test/java/io/appium/java_client/events/listeners/ElementListener2.java @@ -18,10 +18,20 @@ public class ElementListener2 extends TestListener implements ElementEventListen messages.add("Externally defined listener: Attempt to change value of the element"); } + @Override public void beforeChangeValueOf(WebElement element, WebDriver driver, + CharSequence[] keysToSend) { + messages.add("Externally defined listener: Attempt to change value of the element"); + } + @Override public void afterChangeValueOf(WebElement element, WebDriver driver) { messages.add("Externally defined listener: The value of the element was changed"); } + @Override public void afterChangeValueOf(WebElement element, WebDriver driver, + CharSequence[] keysToSend) { + messages.add("Externally defined listener: The value of the element was changed"); + } + @Override protected void add() { SingleListeners.listeners.put(ElementListener2.class, this); }